junit5-r5.10.2/000077500000000000000000000000001455764576500132275ustar00rootroot00000000000000junit5-r5.10.2/.codecov.yml000066400000000000000000000001771455764576500154570ustar00rootroot00000000000000comment: false coverage: status: project: default: threshold: 1 informational: true patch: off junit5-r5.10.2/.editorconfig000066400000000000000000000002041455764576500157000ustar00rootroot00000000000000[*.{kt,kts}] ij_kotlin_allow_trailing_comma = false ij_kotlin_allow_trailing_comma_on_call_site = false [*.kts] indent_style = tab junit5-r5.10.2/.gitattributes000066400000000000000000000001621455764576500161210ustar00rootroot00000000000000* text eol=lf *.bat text eol=crlf *.png binary *.key binary *.jar binary *.ttf binary release-notes-* merge=union junit5-r5.10.2/.github/000077500000000000000000000000001455764576500145675ustar00rootroot00000000000000junit5-r5.10.2/.github/FUNDING.yml000066400000000000000000000006421455764576500164060ustar00rootroot00000000000000# These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel custom: https://junit.org/sponsoring junit5-r5.10.2/.github/ISSUE_TEMPLATE.md000066400000000000000000000015711455764576500173000ustar00rootroot00000000000000## Overview _Replace the following bullet points with your issue description, after answering yourself: **"What kind of issue is this?"**_ - ( ) **Question.** This issue tracker is not the place for questions. If you want to ask how to do something, or to understand why something isn't working the way you expect it to, please first use Stack Overflow or Gitter. https://stackoverflow.com/questions/tagged/junit5 - ( ) **Bug report.** Please provide us the version of JUnit 5 you are using and, if possible, a failing unit test with your bug report. Don't forget to describe the rationale for this issue (e.g. expected vs. actual behavior). - ( ) **Feature request.** Start by telling us what problem you’re trying to solve. Often a solution already exists! Please, don’t send pull requests to implement new features without first getting our support. ## Deliverables - [ ] ... junit5-r5.10.2/.github/ISSUE_TEMPLATE/000077500000000000000000000000001455764576500167525ustar00rootroot00000000000000junit5-r5.10.2/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000011701455764576500214430ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve --- ## Steps to reproduce ## Context - Used versions (Jupiter/Vintage/Platform): - Build Tool/IDE: ## Deliverables - [ ] ... junit5-r5.10.2/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000004511455764576500224770ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project --- ## Deliverables - [ ] ... junit5-r5.10.2/.github/ISSUE_TEMPLATE/question.md000066400000000000000000000006221455764576500211430ustar00rootroot00000000000000--- name: Question about: Please first ask on Gitter or StackOverflow before creating an issue --- This issue tracker is not the place for questions. If you want to ask how to do something, or to understand why something isn't working the way you expect it to, please use Gitter [1] or Stack Overflow [2]. [1] https://gitter.im/junit-team/junit5 [2] https://stackoverflow.com/questions/tagged/junit5 junit5-r5.10.2/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000024431455764576500203730ustar00rootroot00000000000000## Overview --- I hereby agree to the terms of the [JUnit Contributor License Agreement](https://github.com/junit-team/junit5/blob/002a0052926ddee57cf90580fa49bc37e5a72427/CONTRIBUTING.md#junit-contributor-license-agreement). --- ### Definition of Done - [ ] There are no TODOs left in the code - [ ] Method [preconditions](https://junit.org/junit5/docs/snapshot/api/org.junit.platform.commons/org/junit/platform/commons/util/Preconditions.html) are checked and documented in the method's Javadoc - [ ] [Coding conventions](https://github.com/junit-team/junit5/blob/HEAD/CONTRIBUTING.md#coding-conventions) (e.g. for logging) have been followed - [ ] Change is covered by [automated tests](https://github.com/junit-team/junit5/blob/HEAD/CONTRIBUTING.md#tests) including corner cases, errors, and exception handling - [ ] Public API has [Javadoc](https://github.com/junit-team/junit5/blob/HEAD/CONTRIBUTING.md#javadoc) and [`@API` annotations](https://apiguardian-team.github.io/apiguardian/docs/current/api/org/apiguardian/api/API.html) - [ ] Change is documented in the [User Guide](https://junit.org/junit5/docs/snapshot/user-guide/) and [Release Notes](https://junit.org/junit5/docs/snapshot/user-guide/#release-notes) junit5-r5.10.2/.github/actions/000077500000000000000000000000001455764576500162275ustar00rootroot00000000000000junit5-r5.10.2/.github/actions/main-build/000077500000000000000000000000001455764576500202505ustar00rootroot00000000000000junit5-r5.10.2/.github/actions/main-build/action.yml000066400000000000000000000010111455764576500222410ustar00rootroot00000000000000name: Main build description: Sets up JDKs and runs Gradle inputs: arguments: required: true description: Gradle arguments default: build runs: using: "composite" steps: - uses: ./.github/actions/setup-test-jdk - uses: ./.github/actions/run-gradle with: arguments: ${{ inputs.arguments }} - uses: actions/upload-artifact@v3 if: ${{ always() }} with: name: Test Distribution trace files (${{ github.job }}) path: '**/build/test-results/*/trace.json' junit5-r5.10.2/.github/actions/run-gradle/000077500000000000000000000000001455764576500202675ustar00rootroot00000000000000junit5-r5.10.2/.github/actions/run-gradle/action.yml000066400000000000000000000013561455764576500222740ustar00rootroot00000000000000name: Run Gradle description: Sets up Gradle JDKs and runs Gradle inputs: arguments: required: true description: Gradle arguments default: build runs: using: "composite" steps: - uses: actions/setup-java@v3 id: setup-gradle-jdk with: distribution: temurin java-version: 17 - uses: gradle/gradle-build-action@v2 env: JAVA_HOME: ${{ steps.setup-gradle-jdk.outputs.path }} with: arguments: | -Porg.gradle.java.installations.auto-download=false -Pjunit.develocity.predictiveTestSelection.enabled=${{ github.event_name == 'pull_request' }} "-Dscan.value.GitHub job=${{ github.job }}" javaToolchains ${{ inputs.arguments }} junit5-r5.10.2/.github/actions/setup-test-jdk/000077500000000000000000000000001455764576500211125ustar00rootroot00000000000000junit5-r5.10.2/.github/actions/setup-test-jdk/action.yml000066400000000000000000000004551455764576500231160ustar00rootroot00000000000000name: Set up Test JDK description: Sets up the JDK required to run platform-tooling-support-tests runs: using: "composite" steps: - uses: actions/setup-java@v3 with: distribution: temurin java-version: 8 - shell: bash run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV junit5-r5.10.2/.github/dependabot.yml000066400000000000000000000016051455764576500174210ustar00rootroot00000000000000version: 2 registries: gradle-plugin-portal: type: maven-repository url: https://plugins.gradle.org/m2 username: dummy # Required by dependabot password: dummy # Required by dependabot updates: - package-ecosystem: "gradle" directory: "/" registries: - gradle-plugin-portal schedule: interval: "weekly" labels: [ ] - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" labels: [ ] - package-ecosystem: "github-actions" directory: "/.github/actions/main-build" schedule: interval: "weekly" labels: [ ] - package-ecosystem: "github-actions" directory: "/.github/actions/run-gradle" schedule: interval: "weekly" labels: [ ] - package-ecosystem: "github-actions" directory: "/.github/actions/setup-test-jdk" schedule: interval: "weekly" labels: [ ] junit5-r5.10.2/.github/workflows/000077500000000000000000000000001455764576500166245ustar00rootroot00000000000000junit5-r5.10.2/.github/workflows/close-inactive-issues.yml000066400000000000000000000030621455764576500235660ustar00rootroot00000000000000name: Close inactive issues and PRs on: schedule: - cron: "30 1 * * *" workflow_dispatch: jobs: close-issues: runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - uses: actions/stale@v8 with: only-labels: "status: waiting-for-feedback" days-before-stale: 14 days-before-close: 21 stale-issue-label: "status: stale" stale-pr-label: "status: stale" stale-issue-message: > If you would like us to be able to process this issue, please provide the requested information. If the information is not provided within the next 3 weeks, we will be unable to proceed and this issue will be closed. close-issue-message: > Closing due to lack of requested feedback. If you would like to proceed with your contribution, please provide the requested information and we will re-open this issue. stale-pr-message: > If you would like us to be able to process this pull request, please provide the requested information or make the requested changes. If the information is not provided or the requested changes are not made within the next 3 weeks, we will be unable to proceed and this pull request will be closed. close-pr-message: > Closing due to lack of requested feedback. If you would like to proceed with your contribution, please provide the requested information or make the requested changes, and we will re-open this pull request. junit5-r5.10.2/.github/workflows/codeql-analysis.yml000066400000000000000000000017721455764576500224460ustar00rootroot00000000000000name: "CodeQL" on: push: branches: - main - 'releases/**' pull_request: # The branches below must be a subset of the branches above branches: - main - 'releases/**' schedule: - cron: '0 19 * * 3' env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: security-events: write strategy: fail-fast: false matrix: language: - java - javascript steps: - name: Check out repository uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} tools: latest - name: Build uses: ./.github/actions/run-gradle with: arguments: | --no-build-cache -Dscan.tag.CodeQL allMainClasses - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 junit5-r5.10.2/.github/workflows/combine-prs.yml000066400000000000000000000005261455764576500215700ustar00rootroot00000000000000name: Combine PRs on: schedule: - cron: '0 0 * * *' # Every day at 00:00 UTC workflow_dispatch: jobs: combine-prs: if: github.repository == 'junit-team/junit5' runs-on: ubuntu-latest steps: - name: combine-prs uses: github/combine-prs@v3.1.1 with: github_token: ${{ secrets.GH_TOKEN }} junit5-r5.10.2/.github/workflows/cross-version.yml000066400000000000000000000025641455764576500221720ustar00rootroot00000000000000name: Cross-Version on: push: branches: - main - 'releases/**' pull_request: branches: - '*' env: JUNIT_DEVELOCITY_TESTDISTRIBUTION_ENABLED: true GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: openjdk: strategy: fail-fast: false matrix: jdk: [21, 22] name: "OpenJDK ${{ matrix.jdk }}" runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Set up Test JDK uses: ./.github/actions/setup-test-jdk - name: 'Set up JDK ${{ matrix.jdk }}' uses: oracle-actions/setup-java@v1 with: website: jdk.java.net release: ${{ matrix.jdk }} version: latest - name: 'Prepare JDK${{ matrix.jdk }} env var' shell: bash run: echo "JDK${{ matrix.jdk }}=$JAVA_HOME" >> $GITHUB_ENV - name: Build uses: ./.github/actions/run-gradle with: arguments: | -PjavaToolchainVersion=${{ matrix.jdk }} -Dscan.tag.JDK_${{ matrix.jdk }} build - name: Upload Test Distribution trace files uses: actions/upload-artifact@v3 with: name: "Test Distribution trace files (OpenJDK ${{ matrix.jdk }})" path: '**/build/test-results/*/trace.json' junit5-r5.10.2/.github/workflows/gradle-wrapper-validation.yml000066400000000000000000000006361455764576500244200ustar00rootroot00000000000000name: "Validate Gradle Wrapper" on: push: branches: - main - 'releases/**' pull_request: branches: - '*' jobs: validation: name: "Validation" runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 junit5-r5.10.2/.github/workflows/issue-labels.yml000066400000000000000000000007131455764576500217400ustar00rootroot00000000000000name: Label new issues on: issues: types: - opened jobs: label_issues: runs-on: ubuntu-latest permissions: issues: write steps: - uses: actions/github-script@v6 with: script: | github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: ["status: new"] }) junit5-r5.10.2/.github/workflows/main.yml000066400000000000000000000053471455764576500203040ustar00rootroot00000000000000name: CI on: push: branches: - main - 'releases/**' pull_request: branches: - '*' env: JUNIT_DEVELOCITY_TESTDISTRIBUTION_ENABLED: true GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: Linux: runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Install Graphviz run: | sudo apt-get update sudo apt-get install graphviz - name: Install GraalVM uses: graalvm/setup-graalvm@v1 with: version: 'latest' java-version: '17' components: 'native-image' github-token: ${{ secrets.GITHUB_TOKEN }} - name: Build uses: ./.github/actions/main-build with: arguments: | -Ptesting.enableJaCoCo build jacocoRootReport prepareDocsForUploadToGhPages - name: Upload to Codecov.io uses: codecov/codecov-action@v3 Windows: runs-on: windows-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Build uses: ./.github/actions/main-build macOS: runs-on: macos-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Build uses: ./.github/actions/main-build publish_artifacts: name: Publish Snapshot Artifacts needs: linux runs-on: ubuntu-latest if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main') steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Publish uses: ./.github/actions/run-gradle env: ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} with: arguments: publish -x check update_documentation: name: Update Snapshot Documentation concurrency: group: github-pages cancel-in-progress: true needs: Linux runs-on: ubuntu-latest if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && github.ref == 'refs/heads/main' steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Install Graphviz run: | sudo apt-get update sudo apt-get install graphviz - name: Upload Documentation uses: ./.github/actions/run-gradle with: arguments: gitPublishPush -Dscan.tag.Documentation env: GRGIT_USER: ${{ secrets.GH_TOKEN }} junit5-r5.10.2/.github/workflows/reproducible-build.yml000066400000000000000000000012601455764576500231220ustar00rootroot00000000000000name: Reproducible build on: push: branches: - main - 'releases/**' pull_request: branches: - '*' env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: check_build_reproducibility: name: 'Check build reproducibility' runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v3 with: fetch-depth: 1 - name: Restore Gradle cache and display toolchains uses: ./.github/actions/run-gradle with: arguments: --quiet - name: Build and compare checksums shell: bash run: | ./gradle/scripts/checkBuildReproducibility.sh junit5-r5.10.2/.gitignore000066400000000000000000000004411455764576500152160ustar00rootroot00000000000000# Gradle .gradle build # Ignore Gradle GUI config gradle-app.setting # Eclipse .classpath .settings/ .project /bin/ /*/bin # IntelliJ *.iml *.ipr *.iws *.uml **/.idea/* !/.idea/icon.png !/.idea/vcs.xml /out/ /*/out/ # Misc *.log *.graphml coverage.db* .metadata /.sdkmanrc checksums* junit5-r5.10.2/.idea/000077500000000000000000000000001455764576500142075ustar00rootroot00000000000000junit5-r5.10.2/.idea/icon.png000066400000000000000000000076561455764576500156630ustar00rootroot00000000000000PNG  IHDRPLTE,`RJ%b%bwgGG@@RJRI%bXU%bGGX%bRJ`NRJRJRJ%bRJ%b%b%aRJT6%bRJ%bf%b cRJ%b%bRIRJRJ"b$bRJ$aSJ$bTKRJ%b$bQJRJ%bQIRJ&aRJ&bRJ$cPJ"cRKSD%bRJ$bQJRK%b$bRJ$bRJ%b%bUK$c%]'b%bQI%b%b$aUEQI%b+`bȭrObCG$cSK]QH%bRJXQ&b+3gYRTL(i,dZ)cXOVM'gWN'hVN&fSJ1fUK%%d+d`HQd1bUMTJ&e/eN.-eTLPH5g%cSKNIEB65%ULDG=JAɬ `Ħꩦ;/2!#´{wje\E:& 哐`MDI?8** ͵衞盘j䈄b}Pwrlmh^ePLC>2ɻıӾ餢昖~u䌉]upd^I믭W{Fr5j6g \̶ƿZzia[aZYWPLKP/E ActRNSIG)$ʐУW´L,#ԶyOCB=) þqXR?4 侭nšſjbGK 9sOޱO_l)hhO5vsO>:B-hd{;>|Ŝ銣+ ١^=5FJ^@A}ac>nAojQ'Y\wBPKsw[]ADdUZG~faPtzߍyѷvP.BКF@ga^ u;VC^^MK*d?Y%0 ""x^!7 %nO>+/bҞ TjKe0sO{RA'ZJ$11͝,AW Zv ],[,f=`mM<3XvNbOZ"`3+U0 L B-݂)L*#RRЖ@$SL t7C?9hI+ʡpB<6@2g_K(4!vDpj:H7xPg^:"V 5! nV+"(u  U|b2!`b"``ZtE22i-A 0HbI%MLjBz:X8ӄO.U@c92S^Xp*C^ʤ@Cm%QHgS+kYև tjaf$\@-2luK@@ 06TZm_-ŀdKA۩DC !PocfF2P `(<L!B2qzc "{/1mA|wB I@k)9 ~'2 k;A< v ҽ3J؊`jL%hN4#AKfb=/R*Xw,t-fXwAZ^VfYXN' A`b?s9w7oY)̩zY6=5l-:6//||~/2&=9~ʹ/礳n}x\%]_fXĴë B'5ՖrEl)-d< xԬGVm-#B6m*+y@-BT_d Q1Շxq03{fNZh a <dj! `g"sfzD@}r"GdPs"1P}-p@!WQqXUSm£ bG(ۃR> sZdb>Ey`ȝ3IhD:u[7rɌ9S&}{1Ccɪ0oҒYe@ HXdj ,P]t:i&Vڸ 󢶮12L[c~Q.Ƭkם+8!!V9wN{ HN\B&ŷC'Xl.מ|*H ԡ.=[ĐY"6TfS:@ 0J,"b$-2s]`<"Q\k0E=8!S¾v(=6 xМ hNpAP% Rfq3Qy9-?9E+cJMb (h8-7 lL}*`P*[q%j~P)#L_h9-a 8+c#˞5]JR8V!HpLɛ Y#r B0=ao R*԰XpCcՁC;t,/:2DJc1arf J :c:2J^7'wrkX7 ҏ 몷6(¨_0oVM5ֱgj0A ύ 7,?pz/N3k,>nPB_tk'L,^5ĉmkMlM[u0dʾ/6:ҥVm ^QE!@@.x~D1cg]KHw"ڤpi9 Т Q'g*%AD')$2o^R.8F9&03Sp:wnI@\MĂ_eQJئJw~kw Bdx4{[rD|k^y6eH?(i_:׼r[؂QпsSzt`'W_k=^l+jKEbC~Taoa74=E9"^>v  4ofTznXp0IDPL2gM[__wYÙs8]@/fق\oNme[XXͩz]P<\MdflY˺9~rcA*pOp/\ ;c fFND@jP*wĂ~/DY@O(F) u;^tɋ U建_#`SJPQ.wpK I0?>^RO<>ĸ=6']Ή߹Df|"{xer# !(HR\&oƗI~GlɚO!UՒGg59^'dEœVau9r_a2Y6fo0P/;'%>{O !ɘ!O wKoJBOeT8sIENDB`junit5-r5.10.2/.idea/vcs.xml000066400000000000000000000020441455764576500155240ustar00rootroot00000000000000 junit5-r5.10.2/CODE_OF_CONDUCT.md000066400000000000000000000064221455764576500160320ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at team@junit.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq junit5-r5.10.2/CONTRIBUTING.md000066400000000000000000000161631455764576500154670ustar00rootroot00000000000000# Contributing ## JUnit Contributor License Agreement - 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). ### Project Licenses - All modules use [Eclipse Public License v2.0](LICENSE.md). ## Commit Messages As a general rule, the style and formatting of commit messages should follow the guidelines in [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/). In addition, any commit that is related to an existing issue must reference the issue. For example, if a commit in a pull request addresses issue \#999, it must contain the following at the bottom of the commit message. ``` Issue: #999 ``` ## Pull Requests Our [Definition of Done](https://github.com/junit-team/junit5/wiki/Definition-of-Done) (DoD) offers some guidelines on what we expect from a pull request. Feel free to open a pull request that does not fulfill all criteria, e.g. to discuss a certain change before polishing it, but please be aware that we will only merge it once the DoD is met. Please add the following lines to your pull request description: ```markdown --- I hereby agree to the terms of the JUnit Contributor License Agreement. ``` ## Coding Conventions ### Naming Conventions Whenever an acronym is included as part of a type name or method name, keep the first letter of the acronym uppercase and use lowercase for the rest of the acronym. Otherwise, it becomes _impossible_ to perform camel-cased searches in IDEs, and it becomes potentially very difficult for mere humans to read or reason about the element without reading documentation (if documentation even exists). Consider for example a use case needing to support an HTTP URL. Calling the method `getHTTPURL()` is absolutely horrible in terms of usability; whereas, `getHttpUrl()` is great in terms of usability. The same applies for types `HTTPURLProvider` vs `HttpUrlProvider`, etc. Whenever an acronym is included as part of a field name or parameter name: - If the acronym comes at the start of the field or parameter name, use lowercase for the entire acronym -- for example, `String url;`. - Otherwise, keep the first letter of the acronym uppercase and use lowercase for the rest of the acronym -- for example, `String defaultUrl;`. ### Formatting #### Code Code formatting is enforced using the [Spotless](https://github.com/diffplug/spotless) Gradle plugin. You can use `gradle spotlessApply` to format new code and add missing license headers to source files. Formatter and import order settings for Eclipse are available in the repository under [junit-eclipse-formatter-settings.xml](gradle/config/eclipse/junit-eclipse-formatter-settings.xml) and [junit-eclipse.importorder](gradle/config/eclipse/junit-eclipse.importorder), respectively. For IntelliJ IDEA there's a [plugin](https://plugins.jetbrains.com/plugin/6546) you can use in conjunction with the Eclipse settings. It is forbidden to use _wildcard imports_ (e.g., `import static org.junit.jupiter.api.Assertions.*;`) in Java code. #### Documentation Text in `*.adoc` and `*.md` files should be wrapped at 90 characters whenever technically possible. In multi-line bullet point entries, subsequent lines should be indented. ### Spelling Use American English spelling rules when writing documentation as well as for code -- class names, method names, variable names, etc. ### Javadoc - Javadoc comments should be wrapped after 80 characters whenever possible. - This first paragraph must be a single, concise sentence that ends with a period (`.`). - Place `

` on the same line as the first line of a new paragraph and precede `

` with a blank line. - Insert a blank line before at-clauses/tags. - Favor `{@code foo}` over `foo`. - Favor literals (e.g., `{@literal @}`) over HTML entities. - New classes and methods should declare a `@since ...` tag. - Use `@since 5.10` instead of `@since 5.10.0`. - Do not use `@author` tags. Instead, contributors are listed on the [GitHub](https://github.com/junit-team/junit5/graphs/contributors) page. - Do not use verbs in third-person form in the first sentence of the Javadoc for a method -- for example, use "Discover tests..." instead of "Discovers tests...". #### Examples See [`ExtensionContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java) and [`ParameterContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java) for example Javadoc. ### Tests #### Naming - All test classes must end with a `Tests` suffix. - Example test classes that should not be picked up by the build must end with a `TestCase` suffix. #### Assertions - Use `org.junit.jupiter.api.Assertions` for simple assertions. - Use AssertJ when richer assertions are needed. - Do not use `org.junit.Assert` or `junit.framework.Assert`. #### Mocking and Stubbing - Use either [Mockito](https://github.com/mockito/mockito) or hand-written test doubles. ### Logging - In general, logging should be used sparingly. - All logging must be performed via the internal `Logger` façade provided via the JUnit [LoggerFactory](https://github.com/junit-team/junit5/blob/main/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java). - Levels defined in JUnit's [Logger](https://github.com/junit-team/junit5/blob/main/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java) façade, which delegates to Java Util Logging (JUL) for the actual logging. - _error_ (JUL: `SEVERE`, Log4J: `ERROR`): extra information (in addition to an Exception) about errors that will halt execution - _warn_ (JUL: `WARNING`, Log4J: `WARN`): potential usage or configuration errors that should not halt execution - _info_ (JUL: `INFO`, Log4J: `INFO`): information the users might want to know but not by default - _config_ (JUL: `CONFIG`, Log4J: `CONFIG`): information related to configuration of the system (Example: `ServiceLoaderTestEngineRegistry` logs IDs of discovered engines) - _debug_ (JUL: `FINE`, Log4J: `DEBUG`) - _trace_ (JUL: `FINER`, Log4J: `TRACE`) ### Deprecation The JUnit 5 project uses the `@API` annotation from [API Guardian](https://github.com/apiguardian-team/apiguardian). Publicly available interfaces, classes, and methods have a defined lifecycle which is described in detail in the [User Guide](https://junit.org/junit5/docs/current/user-guide/#api-evolution). That following describes the deprecation process followed for API items. To deprecate an item: - Update the `@API.status` to `DEPRECATED`. - Update `@API.since`. Please note `since` describes the version when the status was changed and not the introduction of the element. - Add the `@Deprecated` Java annotation on the item. - Add the `@deprecated` JavaDoc tag to describe the deprecation, and refer to an eventual replacement. - If the item is used in existing code, add `@SuppressWarnings("deprecation")` to make the build pass. junit5-r5.10.2/KEYS000066400000000000000000000073711455764576500137350ustar00rootroot00000000000000This 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----- junit5-r5.10.2/LICENSE-notice.md000066400000000000000000000004741455764576500161170ustar00rootroot00000000000000Open Source Licenses ==================== This product may include a number of subcomponents with separate copyright notices and license terms. Your use of the source code for these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE-.md files. junit5-r5.10.2/LICENSE.md000066400000000000000000000336331455764576500146430ustar00rootroot00000000000000Eclipse Public License - v 2.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 content 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 changes or additions to the Program that are not Modified Works. “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 or any Secondary License (as applicable), including Contributors. “Derivative Works” shall mean any work, whether in Source Code or other form, that is based on (or derived from) the Program and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. “Modified Works” shall mean any work in Source Code or other form that results from an addition to, deletion from, or modification of the contents of the Program, including, for purposes of clarity any new file in Source Code form that contains any contents of the Program. Modified Works shall not include works that contain only declarations, interfaces, types, classes, structures, or files of the Program solely in each case in order to link to, bind by name, or subclass the Program or Modified Works thereof. “Distribute” means the acts of **a)** distributing or **b)** making available in any manner that enables the transfer of a copy. “Source Code” means the form of a Program preferred for making modifications, including but not limited to software source code, documentation source, and configuration files. “Secondary License” means either the GNU General Public License, Version 2.0, or any later versions of that license, including any exceptions or additional permissions as identified by the initial Contributor. ### 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. **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 or other 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. **e)** Notwithstanding the terms of any Secondary License, no Contributor makes additional grants to any Recipient (other than those set forth in this Agreement) as a result of such Recipient's receipt of the Program under the terms of a Secondary License (if permitted under the terms of Section 3). ### 3. Requirements **3.1** If a Contributor Distributes the Program in any form, then: * **a)** the Program must also be made available as Source Code, in accordance with section 3.2, and the Contributor must accompany the Program with a statement that the Source Code for the Program is available under this Agreement, and informs Recipients how to obtain it in a reasonable manner on or through a medium customarily used for software exchange; and * **b)** the Contributor may Distribute the Program under a license different than this Agreement, provided that such license: * **i)** effectively disclaims on behalf of all other 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 other Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; * **iii)** does not attempt to limit or alter the recipients' rights in the Source Code under section 3.2; and * **iv)** requires any subsequent distribution of the Program by any party to be under a license that satisfies the requirements of this section 3. **3.2** When the Program is Distributed as Source Code: * **a)** it must be made available under this Agreement, or if the Program **(i)** is combined with other material in a separate file or files made available under a Secondary License, and **(ii)** the initial Contributor attached to the Source Code the notice described in Exhibit A of this Agreement, then the Program may be made available under the terms of such Secondary Licenses, and * **b)** a copy of this Agreement must be included with each copy of the Program. **3.3** Contributors may not remove or alter any copyright, patent, trademark, attribution notices, disclaimers of warranty, or limitations of liability (“notices”) contained within the Program from any copy of the Program which they Distribute, provided that Contributors may add their own appropriate notices. ### 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, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, 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, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, 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. Nothing in this Agreement is intended to be enforceable by any entity that is not a Contributor or Recipient. No third-party beneficiary rights are created under this Agreement. #### Exhibit A - Form of Secondary Licenses Notice > “This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), version(s), and exceptions or additional permissions here}.” Simply including a copy of this Agreement, including this Exhibit A is not sufficient to license the Source Code under Secondary Licenses. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. junit5-r5.10.2/README.md000066400000000000000000000123071455764576500145110ustar00rootroot00000000000000# JUnit 5 This repository is the home of _JUnit 5_. [![Support JUnit](https://img.shields.io/badge/%F0%9F%92%9A-Support%20JUnit-brightgreen.svg)](https://junit.org/sponsoring) ## Latest Releases - General Availability (GA): [JUnit 5.10.2](https://github.com/junit-team/junit5/releases/tag/r5.10.2) (February 4, 2024) - Preview (Milestone/Release Candidate): N/A ## Documentation - [User Guide] - [Javadoc] - [Release Notes] - [Samples] ## Contributing Contributions to JUnit 5 are both welcomed and appreciated. For specific guidelines regarding contributions, please see [CONTRIBUTING.md] in the root directory of the project. Those willing to use milestone or SNAPSHOT releases are encouraged to file feature requests and bug reports using the project's [issue tracker](https://github.com/junit-team/junit5/issues). Issues marked with an `up-for-grabs` label are specifically targeted for community contributions. ## Getting Help Ask JUnit 5 related questions on [StackOverflow] or chat with the community on [Gitter]. ## Continuous Integration Builds [![CI Status](https://github.com/junit-team/junit5/workflows/CI/badge.svg)](https://github.com/junit-team/junit5/actions) [![Cross-Version Status](https://github.com/junit-team/junit5/workflows/Cross-Version/badge.svg)](https://github.com/junit-team/junit5/actions) Official CI build server for JUnit 5. Used to perform quick checks on submitted pull requests and for build matrices including the latest released OpenJDK and early access builds of the next OpenJDK. ## Code Coverage Code coverage using [JaCoCo] for the latest build is available on [Codecov]. A code coverage report can also be generated locally via the [Gradle Wrapper] by executing `./gradlew -Ptesting.enableJaCoCo clean jacocoRootReport`. The results will be available in `build/reports/jacoco/jacocoRootReport/html/index.html`. ## Develocity [![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.junit.org/scans) JUnit 5 utilizes [Develocity](https://gradle.com/) for [Build Scans](https://scans.gradle.com/), [Build Cache](https://docs.gradle.org/current/userguide/build_cache.html), [Predictive Test Selection](https://docs.gradle.com/enterprise/predictive-test-selection/), and [Test Distribution](https://docs.gradle.com/enterprise/test-distribution/). The latest Build Scans are available on [ge.junit.org](https://ge.junit.org/). Currently, only core team members can publish Build Scans and use Test Distribution on that server. You can, however, publish a Build Scan to [scans.gradle.com](https://scans.gradle.com/) by using the `--scan` parameter explicitly. The remote Build Cache is enabled by default for everyone so that local builds can reuse task outputs from previous CI builds. ## Building from Source You need [JDK 17] to build JUnit 5. [Gradle toolchains] are used to detect and potentially download additional JDKs for compilation and test execution. All modules can be _built_ and _tested_ with the [Gradle Wrapper] using the following command. `./gradlew build` ## Installing in Local Maven Repository All modules can be _installed_ with the [Gradle Wrapper] in a local Maven repository for consumption in other projects via the following command. `./gradlew publishToMavenLocal` ## Dependency Metadata [![JUnit Jupiter version](https://img.shields.io/maven-central/v/org.junit.jupiter/junit-jupiter/5..svg?color=25a162&label=Jupiter)](https://central.sonatype.com/search?namespace=org.junit.jupiter) [![JUnit Vintage version](https://img.shields.io/maven-central/v/org.junit.vintage/junit-vintage-engine/5..svg?color=25a162&label=Vintage)](https://central.sonatype.com/search?namespace=org.junit.vintage) [![JUnit Platform version](https://img.shields.io/maven-central/v/org.junit.platform/junit-platform-commons/1..svg?color=25a162&label=Platform)](https://central.sonatype.com/search?namespace=org.junit.platform) Consult the [Dependency Metadata] section of the [User Guide] for a list of all artifacts of the JUnit Platform, JUnit Jupiter, and JUnit Vintage. See also for releases and for snapshots. [Codecov]: https://codecov.io/gh/junit-team/junit5 [CONTRIBUTING.md]: https://github.com/junit-team/junit5/blob/HEAD/CONTRIBUTING.md [Dependency Metadata]: https://junit.org/junit5/docs/current/user-guide/#dependency-metadata [Gitter]: https://gitter.im/junit-team/junit5 [Gradle toolchains]: https://docs.gradle.org/current/userguide/toolchains.html [Gradle Wrapper]: https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:using_wrapper [JaCoCo]: https://www.eclemma.org/jacoco/ [Javadoc]: https://junit.org/junit5/docs/current/api/ [JDK 17]: https://foojay.io/almanac/java-17/ [Release Notes]: https://junit.org/junit5/docs/current/release-notes/ [Samples]: https://github.com/junit-team/junit5-samples [StackOverflow]: https://stackoverflow.com/questions/tagged/junit5 [User Guide]: https://junit.org/junit5/docs/current/user-guide/ junit5-r5.10.2/SECURITY.md000066400000000000000000000004351455764576500150220ustar00rootroot00000000000000# Security Policy ## Supported Versions | Version | Supported | | ------- | ------------------ | | 5.9.x | :white_check_mark: | | < 5.9 | :x: | ## Reporting a Vulnerability To report a security vulnerability, please send an email to security@junit.org. junit5-r5.10.2/build.gradle.kts000066400000000000000000000037001455764576500163060ustar00rootroot00000000000000plugins { alias(libs.plugins.nohttp) alias(libs.plugins.nexusPublish) id("junitbuild.base-conventions") id("junitbuild.build-metadata") id("junitbuild.dependency-update-check") id("junitbuild.jacoco-aggregation-conventions") id("junitbuild.temp-maven-repo") } description = "JUnit 5" val license by extra(License( name = "Eclipse Public License v2.0", url = uri("https://www.eclipse.org/legal/epl-v20.html"), headerFile = layout.projectDirectory.file("gradle/config/spotless/eclipse-public-license-2.0.java") )) val platformProjects by extra(listOf( projects.junitPlatformCommons, projects.junitPlatformConsole, projects.junitPlatformConsoleStandalone, projects.junitPlatformEngine, projects.junitPlatformJfr, projects.junitPlatformLauncher, projects.junitPlatformReporting, projects.junitPlatformRunner, projects.junitPlatformSuite, projects.junitPlatformSuiteApi, projects.junitPlatformSuiteCommons, projects.junitPlatformSuiteEngine, projects.junitPlatformTestkit ).map { it.dependencyProject }) val jupiterProjects by extra(listOf( projects.junitJupiter, projects.junitJupiterApi, projects.junitJupiterEngine, projects.junitJupiterMigrationsupport, projects.junitJupiterParams ).map { it.dependencyProject }) val vintageProjects by extra(listOf( projects.junitVintageEngine.dependencyProject )) val mavenizedProjects by extra(platformProjects + jupiterProjects + vintageProjects) val modularProjects by extra(mavenizedProjects - listOf(projects.junitPlatformConsoleStandalone.dependencyProject)) dependencies { (modularProjects + listOf(projects.platformTests.dependencyProject)).forEach { jacocoAggregation(project(it.path)) } } nexusPublishing { packageGroup = "org.junit" repositories { sonatype() } } nohttp { source.exclude("**/.gradle/**", "gradle/plugins/**/build/**", "buildSrc/build/**") } tasks.checkstyleNohttp { notCompatibleWithConfigurationCache("https://github.com/spring-io/nohttp/issues/61") } junit5-r5.10.2/gradle.properties000066400000000000000000000022701455764576500166040ustar00rootroot00000000000000group = org.junit version = 5.10.2 jupiterGroup = org.junit.jupiter platformGroup = org.junit.platform platformVersion = 1.10.2 vintageGroup = org.junit.vintage vintageVersion = 5.10.2 # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby # The exports are needed due to https://github.com/diffplug/spotless/issues/834 org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError \ --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED org.gradle.caching=true org.gradle.parallel=true org.gradle.java.installations.fromEnv=JDK8,JDK18,JDK19,JDK20,JDK21,JDK22 org.gradle.kotlin.dsl.allWarningsAsErrors=true # Test Distribution gradle.internal.testdistribution.writeTraceFile=true # Omit automatic compile dependency on kotlin-stdlib # https://kotlinlang.org/docs/gradle.html#dependency-on-the-standard-library kotlin.stdlib.default.dependency=false junit5-r5.10.2/gradle/000077500000000000000000000000001455764576500144655ustar00rootroot00000000000000junit5-r5.10.2/gradle/config/000077500000000000000000000000001455764576500157325ustar00rootroot00000000000000junit5-r5.10.2/gradle/config/checkstyle/000077500000000000000000000000001455764576500200705ustar00rootroot00000000000000junit5-r5.10.2/gradle/config/checkstyle/checkstyleMain.xml000066400000000000000000000024611455764576500235600ustar00rootroot00000000000000 junit5-r5.10.2/gradle/config/checkstyle/checkstyleTest.xml000066400000000000000000000015061455764576500236120ustar00rootroot00000000000000 junit5-r5.10.2/gradle/config/checkstyle/suppressions.xml000066400000000000000000000007371455764576500233760ustar00rootroot00000000000000 junit5-r5.10.2/gradle/config/eclipse/000077500000000000000000000000001455764576500173565ustar00rootroot00000000000000junit5-r5.10.2/gradle/config/eclipse/junit-eclipse-formatter-settings.xml000066400000000000000000000750071455764576500265230ustar00rootroot00000000000000 junit5-r5.10.2/gradle/config/eclipse/junit-eclipse.importorder000066400000000000000000000001521455764576500244170ustar00rootroot00000000000000#Organize Import Order 0=java 1=javax 2=jdk 3=aQute 4=junit 5=de 6=com 7=example 8=extensions 9=io 10=org junit5-r5.10.2/gradle/config/spotless/000077500000000000000000000000001455764576500176065ustar00rootroot00000000000000junit5-r5.10.2/gradle/config/spotless/eclipse-public-license-2.0.java000066400000000000000000000004721455764576500252710ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ junit5-r5.10.2/gradle/libs.versions.toml000066400000000000000000000123011455764576500201570ustar00rootroot00000000000000[versions] ant = "1.10.13" apiguardian = "1.1.2" asciidoctorj-pdf = "2.3.9" asciidoctor-plugins = "4.0.0-alpha.1" # Check if workaround in documentation.gradle.kts can be removed when upgrading assertj = "3.24.2" bnd = "6.4.0" checkstyle = "10.12.1" gradleVersionsPlugin = "0.47.0" jacoco = "0.8.7" jmh = "1.36" junit4 = "4.13.2" junit4Osgi = "4.13.2_1" junit4Min = "4.12" ktlint = "0.48.2" log4j = "2.20.0" opentest4j = "1.3.0" openTestReporting = "0.1.0-M1" surefire = "3.1.2" xmlunit = "2.9.1" [libraries] ant = { module = "org.apache.ant:ant", version.ref = "ant" } ant-junit = { module = "org.apache.ant:ant-junit", version.ref = "ant" } ant-junitlauncher = { module = "org.apache.ant:ant-junitlauncher", version.ref = "ant" } apiguardian = { module = "org.apiguardian:apiguardian-api", version.ref = "apiguardian" } archunit = { module = "com.tngtech.archunit:archunit-junit5", version = "1.0.1" } assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } bartholdy = { module = "de.sormuras:bartholdy", version = "0.2.3" } bndlib = { module = "biz.aQute.bnd:biz.aQute.bndlib", version.ref = "bnd" } checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.161" } commons-io = { module = "commons-io:commons-io", version = "2.13.0" } gradle-commonCustomUserData = { module = "com.gradle:common-custom-user-data-gradle-plugin", version = "1.11" } gradle-foojayResolver = { module = "org.gradle.toolchains:foojay-resolver", version = "0.6.0" } gradle-enterprise = { module = "com.gradle:gradle-enterprise-gradle-plugin", version = "3.14" } gradle-bnd = { module = "biz.aQute.bnd:biz.aQute.bnd.gradle", version.ref = "bnd" } gradle-shadow = { module = "com.github.johnrengelman:shadow", version = "8.1.1" } gradle-spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version = "6.19.0" } gradle-versions = { module = "com.github.ben-manes:gradle-versions-plugin", version.ref = "gradleVersionsPlugin" } groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.13" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.21" } hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" } jfrunit = { module = "org.moditect.jfrunit:jfrunit-core", version = "1.0.0.Alpha2" } jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" } jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" } joox = { module = "org.jooq:joox", version = "2.0.0" } junit4 = { module = "junit:junit", version = { require = "[4.12,)", prefer = "4.13.2" } } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.7.2" } log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4j" } maven = { module = "org.apache.maven:apache-maven", version = "3.9.3" } mavenSurefirePlugin = { module = "org.apache.maven.plugins:maven-surefire-plugin", version.ref = "surefire" } memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.6.1" } mockito = { module = "org.mockito:mockito-junit-jupiter", version = "5.4.0" } opentest4j = { module = "org.opentest4j:opentest4j", version.ref = "opentest4j" } openTestReporting-events = { module = "org.opentest4j.reporting:open-test-reporting-events", version.ref = "openTestReporting" } openTestReporting-tooling = { module = "org.opentest4j.reporting:open-test-reporting-tooling", version.ref = "openTestReporting" } picocli = { module = "info.picocli:picocli", version = "4.7.5" } slf4j-julBinding = { module = "org.slf4j:slf4j-jdk14", version = "2.0.7" } spock1 = { module = "org.spockframework:spock-core", version = "1.3-groovy-2.5" } univocity-parsers = { module = "com.univocity:univocity-parsers", version = "2.9.1" } xmlunit-assertj = { module = "org.xmlunit:xmlunit-assertj3", version.ref = "xmlunit" } xmlunit-placeholders = { module = "org.xmlunit:xmlunit-placeholders", version.ref = "xmlunit" } testingAnnotations = { module = "com.gradle:gradle-enterprise-testing-annotations", version = "1.1" } # Only declared here so Dependabot knows when to update the referenced versions asciidoctorj-pdf = { module = "org.asciidoctor:asciidoctorj-pdf", version.ref = "asciidoctorj-pdf" } [bundles] ant = ["ant", "ant-junit", "ant-junitlauncher"] log4j = ["log4j-core", "log4j-jul"] xmlunit = ["xmlunit-assertj", "xmlunit-placeholders"] [plugins] asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor-plugins" } asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor-plugins" } buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.3" } gitPublish = { id = "org.ajoberstar.git-publish", version = "4.2.0" } jmh = { id = "me.champeau.jmh", version = "0.7.1" } nohttp = { id = "io.spring.nohttp", version = "0.0.11" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0-rc-1" } plantuml = { id = "io.freefair.plantuml", version = "8.4" } versions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersionsPlugin" } junit5-r5.10.2/gradle/plugins/000077500000000000000000000000001455764576500161465ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/build-parameters/000077500000000000000000000000001455764576500214065ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/build-parameters/build.gradle.kts000066400000000000000000000051671455764576500244760ustar00rootroot00000000000000plugins { alias(libs.plugins.buildParameters) } group = "junitbuild" buildParameters { pluginId("junitbuild.build-parameters") bool("ci") { description = "Whether or not this build is running in a CI environment" defaultValue = false fromEnvironment() } integer("javaToolchainVersion") { description = "Defines the Java toolchain version to use for compiling code" } group("documentation") { description = "Parameters controlling how the documentation is built" bool("replaceCurrentDocs") { description = "The documentation that is being deployed will replace what's currently deployed as 'current'" defaultValue = false } } group("junit") { group("develocity") { description = "Parameters controlling Develocity features" group("buildCache") { string("server") { description = "Remote build cache server address (protocol and hostname), e.g. https://eu-build-cache-ge.junit.org" } } group("predictiveTestSelection") { bool("enabled") { description = "Whether or not to use Predictive Test Selection for selecting tests to execute" defaultValue = true } } group("testDistribution") { bool("enabled") { description = "Whether or not to use Test Distribution for executing tests" defaultValue = false fromEnvironment() } integer("maxLocalExecutors") { description = "How many local executors to use for executing tests" defaultValue = 1 } integer("maxRemoteExecutors") { description = "How many remote executors to request for executing tests" } } } } group("testing") { description = "Testing related parameters" bool("enableJaCoCo") { description = "Enables JaCoCo test coverage reporting" defaultValue = false } bool("enableJFR") { description = "Enables Java Flight Recorder functionality" defaultValue = false } integer("retries") { description = "Configures the number of times failing test are retried" } } group("publishing") { bool("signArtifacts") { description = "Sign artifacts before publishing them to Maven repos" } } group("manifest") { string("buildTimestamp") { description = "Overrides the value of the 'Build-Date' and 'Build-Time' jar manifest entries. Can be set as a String (e.g. '2023-11-05 17:49:13.996+0100') or as seconds since the epoch." fromEnvironment("SOURCE_DATE_EPOCH") // see https://reproducible-builds.org/docs/source-date-epoch/ } string("builtBy") { description = "Overrides the value of the 'Built-By' jar manifest entry" } string("createdBy") { description = "Overrides the value of the 'Created-By' jar manifest entry" } } } junit5-r5.10.2/gradle/plugins/build.gradle.kts000066400000000000000000000000521455764576500212220ustar00rootroot00000000000000plugins { alias(libs.plugins.versions) } junit5-r5.10.2/gradle/plugins/common/000077500000000000000000000000001455764576500174365ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/build.gradle.kts000066400000000000000000000006761455764576500225260ustar00rootroot00000000000000plugins { `kotlin-dsl` } repositories { gradlePluginPortal() } dependencies { implementation(projects.buildParameters) implementation(kotlin("gradle-plugin")) implementation(libs.gradle.bnd) implementation(libs.gradle.commonCustomUserData) implementation(libs.gradle.enterprise) implementation(libs.gradle.foojayResolver) implementation(libs.gradle.shadow) implementation(libs.gradle.spotless) implementation(libs.gradle.versions) } junit5-r5.10.2/gradle/plugins/common/src/000077500000000000000000000000001455764576500202255ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/000077500000000000000000000000001455764576500211515ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/000077500000000000000000000000001455764576500224515ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/ConfigurationContainerExtensions.kt000066400000000000000000000010001455764576500315320ustar00rootroot00000000000000 import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ConfigurationContainer import org.gradle.kotlin.dsl.NamedDomainObjectContainerCreatingDelegateProvider val ConfigurationContainer.creatingResolvable get() = creatingResolvable {} fun ConfigurationContainer.creatingResolvable(configuration: Configuration.() -> Unit) = NamedDomainObjectContainerCreatingDelegateProvider.of(this) { isCanBeResolved = true isCanBeConsumed = false configuration() } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt000066400000000000000000000003551455764576500271170ustar00rootroot00000000000000import org.gradle.api.JavaVersion open class JavaLibraryExtension { var mainJavaVersion: JavaVersion = JavaVersion.VERSION_1_8 var testJavaVersion: JavaVersion = JavaVersion.VERSION_17 var configureRelease: Boolean = true } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/License.kt000066400000000000000000000002141455764576500243700ustar00rootroot00000000000000import org.gradle.api.file.RegularFile import java.net.URI data class License(val name: String, val url: URI, val headerFile: RegularFile) junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/ProjectExtensions.kt000066400000000000000000000012331455764576500264760ustar00rootroot00000000000000import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalog import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.kotlin.dsl.the val Project.javaModuleName: String get() = "org." + this.name.replace('-', '.') fun Project.requiredVersionFromLibs(name: String) = libsVersionCatalog.findVersion(name).get().requiredVersion fun Project.dependencyFromLibs(name: String) = libsVersionCatalog.findLibrary(name).get() fun Project.bundleFromLibs(name: String) = libsVersionCatalog.findBundle(name).get() private val Project.libsVersionCatalog: VersionCatalog get() = the().named("libs") junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/TaskExtensions.kt000066400000000000000000000002631455764576500257740ustar00rootroot00000000000000import org.gradle.api.Task import org.gradle.internal.os.OperatingSystem fun Task.trackOperationSystemAsInput() = inputs.property("os", OperatingSystem.current().familyName) junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.base-conventions.gradle.kts000066400000000000000000000001571455764576500320610ustar00rootroot00000000000000plugins { eclipse idea id("junitbuild.java-toolchain-conventions") id("junitbuild.spotless-conventions") } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts000066400000000000000000000017201455764576500314560ustar00rootroot00000000000000import java.time.Instant import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatterBuilder plugins { id("junitbuild.build-parameters") } val dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE val timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSSZ") val buildTimeAndDate = buildParameters.manifest.buildTimestamp .map { it.toLongOrNull() ?.let { s -> Instant.ofEpochSecond(s).atOffset(ZoneOffset.UTC) } ?: DateTimeFormatterBuilder() .append(dateFormatter) .appendLiteral(' ') .append(timeFormatter) .toFormatter() .parse(it) } .orNull ?: OffsetDateTime.now() val buildDate: String by extra { dateFormatter.format(buildTimeAndDate) } val buildTime: String by extra { timeFormatter.format(buildTimeAndDate) } val buildRevision: String by extra { providers.exec { commandLine("git", "rev-parse", "--verify", "HEAD") }.standardOutput.asText.get() } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts000066400000000000000000000006441455764576500332560ustar00rootroot00000000000000plugins { id("com.github.ben-manes.versions") } tasks.dependencyUpdates { checkConstraints = true resolutionStrategy { componentSelection { all { val rejected = listOf("alpha", "beta", "rc", "cr", "m", "preview", "b", "ea") .map { qualifier -> Regex("(?i).*[.-]$qualifier[.\\d-+]*") } .any { it.matches(candidate.version) } if (rejected) { reject("Release candidate") } } } } } junitbuild.jacoco-aggregation-conventions.gradle.kts000066400000000000000000000003121455764576500346040ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlinplugins { id("junitbuild.jacoco-conventions") `jacoco-report-aggregation` } reporting { reports { create("jacocoRootReport") { testType = TestSuiteType.UNIT_TEST } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts000066400000000000000000000003261455764576500324030ustar00rootroot00000000000000plugins { jacoco id("junitbuild.build-parameters") } jacoco { toolVersion = requiredVersionFromLibs("jacoco") } tasks.withType().configureEach { enabled = buildParameters.testing.enableJaCoCo } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts000066400000000000000000000016221455764576500333220ustar00rootroot00000000000000import org.gradle.api.attributes.LibraryElements.CLASSES import org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE plugins { java id("junitbuild.build-parameters") id("junitbuild.jacoco-conventions") } val mavenizedProjects: List by rootProject.extra tasks.withType().configureEach { configure { isEnabled = buildParameters.testing.enableJaCoCo } } val codeCoverageClassesJar by tasks.registering(Jar::class) { from(tasks.jar.map { zipTree(it.archiveFile) }) archiveClassifier = "jacoco" enabled = project in mavenizedProjects duplicatesStrategy = DuplicatesStrategy.INCLUDE } configurations.create("codeCoverageReportClasses") { isCanBeResolved = false isCanBeConsumed = true isTransitive = false attributes.attribute(LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements::class, CLASSES)) outgoing.artifact(codeCoverageClassesJar) } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts000066400000000000000000000224221455764576500335310ustar00rootroot00000000000000import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import junitbuild.java.ModuleCompileOptions import junitbuild.java.ModulePathArgumentProvider import junitbuild.java.PatchModuleArgumentProvider plugins { `java-library` eclipse idea checkstyle id("junitbuild.base-conventions") id("junitbuild.build-parameters") id("junitbuild.jacoco-java-conventions") } val mavenizedProjects: List by rootProject.extra val modularProjects: List by rootProject.extra val buildDate: String by rootProject.extra val buildTime: String by rootProject.extra val buildRevision: Any by rootProject.extra val extension = extensions.create("javaLibrary") val moduleSourceDir = layout.projectDirectory.dir("src/module/$javaModuleName") val combinedModuleSourceDir = layout.buildDirectory.dir("module") val moduleOutputDir = layout.buildDirectory.dir("classes/java/module") val javaVersion = JavaVersion.current() eclipse { jdt { file { // Set properties for org.eclipse.jdt.core.prefs withProperties { // Configure Eclipse projects with -parameters compiler flag. setProperty("org.eclipse.jdt.core.compiler.codegen.methodParameters", "generate") } } } } java { modularity.inferModulePath = false } if (project in mavenizedProjects) { apply(plugin = "junitbuild.publishing-conventions") apply(plugin = "junitbuild.osgi-conventions") java { withJavadocJar() withSourcesJar() } tasks.javadoc { options { memberLevel = JavadocMemberLevel.PROTECTED header = project.name encoding = "UTF-8" locale = "en" (this as StandardJavadocDocletOptions).apply { addBooleanOption("Xdoclint:all,-missing,-reference", true) addBooleanOption("XD-Xlint:none", true) addBooleanOption("html5", true) addMultilineStringsOption("tag").value = listOf( "apiNote:a:API Note:", "implNote:a:Implementation Note:" ) use(true) noTimestamp(true) } } } tasks.named("javadocJar").configure { from(tasks.javadoc.map { File(it.destinationDir, "element-list") }) { // For compatibility with older tools, e.g. NetBeans 11 rename { "package-list" } } } tasks.named("sourcesJar").configure { from(moduleSourceDir) { include("module-info.java") } duplicatesStrategy = DuplicatesStrategy.EXCLUDE } pluginManager.withPlugin("java-test-fixtures") { val javaComponent = components["java"] as AdhocComponentWithVariants javaComponent.withVariantsFromConfiguration(configurations["testFixturesApiElements"]) { skip() } javaComponent.withVariantsFromConfiguration(configurations["testFixturesRuntimeElements"]) { skip() } } configure { publications { named("maven") { from(components["java"]) versionMapping { allVariants { fromResolutionResult() } } pom { description = provider { "Module \"${project.name}\" of JUnit 5." } } } } } } else { tasks { jar { enabled = false } javadoc { enabled = false } } } tasks.withType().configureEach { isPreserveFileTimestamps = false isReproducibleFileOrder = true dirMode = Integer.parseInt("0755", 8) fileMode = Integer.parseInt("0644", 8) } normalization { runtimeClasspath { metaInf { // Ignore inconsequential JAR manifest attributes such as timestamps and the commit checksum. // This is used when checking whether runtime classpaths, e.g. of test tasks, have changed and // improves cacheability of such tasks. ignoreAttribute("Built-By") ignoreAttribute("Build-Date") ignoreAttribute("Build-Time") ignoreAttribute("Build-Revision") ignoreAttribute("Created-By") } } } val allMainClasses by tasks.registering { dependsOn(tasks.classes) } val prepareModuleSourceDir by tasks.registering(Sync::class) { from(moduleSourceDir) from(sourceSets.matching { it.name.startsWith("main") }.map { it.allJava }) into(combinedModuleSourceDir.map { it.dir(javaModuleName) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } val compileModule by tasks.registering(JavaCompile::class) { dependsOn(allMainClasses) enabled = project in modularProjects source = fileTree(combinedModuleSourceDir).builtBy(prepareModuleSourceDir) destinationDirectory = moduleOutputDir sourceCompatibility = "9" targetCompatibility = "9" classpath = files() options.release = 9 options.compilerArgs.addAll(listOf( // Suppress warnings for automatic modules: org.apiguardian.api, org.opentest4j "-Xlint:all,-requires-automatic,-requires-transitive-automatic", "-Werror", // Terminates compilation when warnings occur. "--module-version", "${project.version}", )) val moduleOptions = objects.newInstance(ModuleCompileOptions::class) extensions.add("moduleOptions", moduleOptions) moduleOptions.modulePath.from(configurations.compileClasspath) options.compilerArgumentProviders.add(objects.newInstance(ModulePathArgumentProvider::class, project, combinedModuleSourceDir, modularProjects).apply { modulePath.from(moduleOptions.modulePath) }) options.compilerArgumentProviders.addAll(modularProjects.map { objects.newInstance(PatchModuleArgumentProvider::class, project, it) }) modularity.inferModulePath = false doFirst { options.allCompilerArgs.forEach { logger.info(it) } } } tasks.withType().configureEach { from(rootDir) { include("LICENSE.md", "LICENSE-notice.md") into("META-INF") } val suffix = archiveClassifier.getOrElse("") if (suffix.isBlank() || this is ShadowJar) { dependsOn(allMainClasses, compileModule) from(moduleOutputDir.map { it.dir(javaModuleName) }) { include("module-info.class") } } } tasks.jar { manifest { attributes( "Created-By" to (buildParameters.manifest.createdBy.orNull ?: "${System.getProperty("java.version")} (${System.getProperty("java.vendor")} ${System.getProperty("java.vm.version")})"), "Built-By" to buildParameters.manifest.builtBy.orElse("JUnit Team"), "Build-Date" to buildDate, "Build-Time" to buildTime, "Build-Revision" to buildRevision, "Specification-Title" to project.name, "Specification-Version" to (project.version as String).substringBefore('-'), "Specification-Vendor" to "junit.org", "Implementation-Title" to project.name, "Implementation-Version" to project.version, "Implementation-Vendor" to "junit.org" ) } } tasks.withType().configureEach { outputs.doNotCacheIf("Shadow jar contains a Manifest with Build-Time") { true } } tasks.withType().configureEach { options.encoding = "UTF-8" } tasks.compileJava { // See: https://docs.oracle.com/en/java/javase/12/tools/javac.html options.compilerArgs.addAll(listOf( "-Xlint:all", // Enables all recommended warnings. "-Werror" // Terminates compilation when warnings occur. )) } tasks.compileTestJava { // See: https://docs.oracle.com/en/java/javase/12/tools/javac.html options.compilerArgs.addAll(listOf( "-Xlint", // Enables all recommended warnings. "-Xlint:-overrides", // Disables "method overrides" warnings. "-Werror", // Terminates compilation when warnings occur. "-parameters" // Generates metadata for reflection on method parameters. )) } afterEvaluate { configurations { apiElements { attributes { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.majorVersion.toInt()) } } runtimeElements { attributes { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.majorVersion.toInt()) } } } tasks { compileJava { if (extension.configureRelease) { options.release = extension.mainJavaVersion.majorVersion.toInt() } else { sourceCompatibility = extension.mainJavaVersion.majorVersion targetCompatibility = extension.mainJavaVersion.majorVersion } } compileTestJava { if (extension.configureRelease) { options.release = extension.testJavaVersion.majorVersion.toInt() } else { sourceCompatibility = extension.testJavaVersion.majorVersion targetCompatibility = extension.testJavaVersion.majorVersion } } } pluginManager.withPlugin("groovy") { tasks.named("compileGroovy").configure { // Groovy compiler does not support the --release flag. sourceCompatibility = extension.mainJavaVersion.majorVersion targetCompatibility = extension.mainJavaVersion.majorVersion } tasks.named("compileTestGroovy").configure { // Groovy compiler does not support the --release flag. sourceCompatibility = extension.testJavaVersion.majorVersion targetCompatibility = extension.testJavaVersion.majorVersion } } } checkstyle { toolVersion = requiredVersionFromLibs("checkstyle") configDirectory = rootProject.layout.projectDirectory.dir("gradle/config/checkstyle") } tasks { checkstyleMain { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) } checkstyleTest { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } } pluginManager.withPlugin("java-test-fixtures") { tasks.named("checkstyleTestFixtures") { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } tasks.named("compileTestFixturesJava") { options.release = extension.testJavaVersion.majorVersion.toInt() } } junitbuild.java-multi-release-sources.gradle.kts000066400000000000000000000022171455764576500336740ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlinimport org.gradle.configurationcache.extensions.capitalized plugins { id("junitbuild.java-library-conventions") } val mavenizedProjects: List by rootProject.extra listOf(9, 17).forEach { javaVersion -> val sourceSet = sourceSets.register("mainRelease${javaVersion}") { compileClasspath += sourceSets.main.get().output runtimeClasspath += sourceSets.main.get().output java { setSrcDirs(setOf("src/main/java${javaVersion}")) } } configurations.named(sourceSet.get().compileClasspathConfigurationName).configure { extendsFrom(configurations.compileClasspath.get()) } tasks { named("allMainClasses").configure { dependsOn(sourceSet.get().classesTaskName) } named(sourceSet.get().compileJavaTaskName).configure { options.release = javaVersion } named("checkstyle${sourceSet.name.capitalized()}").configure { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) } if (project in mavenizedProjects) { javadoc { source(sourceSet.get().allJava) } named("sourcesJar").configure { from(sourceSet.get().allSource) } } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts000066400000000000000000000025601455764576500324020ustar00rootroot00000000000000import java.util.jar.JarEntry import java.util.jar.JarFile import java.util.jar.JarOutputStream import org.gradle.api.internal.file.archive.ZipCopyAction import java.nio.file.Files // This registers a `doLast` action to rewrite the timestamps of the project's output JAR afterEvaluate { val jarTask = (tasks.findByName("shadowJar") ?: tasks["jar"]) as Jar jarTask.doLast { val newFile = Files.createTempFile("rewrite-timestamp", null).toFile() val originalOutput = jarTask.archiveFile.get().asFile newFile.outputStream().use { os -> val newJarStream = JarOutputStream(os) val oldJar = JarFile(originalOutput) fun sortAlwaysFirst(name: String): Comparator = Comparator { a, b -> when { a.name == name -> -1 b.name == name -> 1 else -> 0 } } oldJar.entries() .toList() .distinctBy { it.name } .sortedWith(sortAlwaysFirst("META-INF/") .then(sortAlwaysFirst("META-INF/MANIFEST.MF")) .thenBy { it.name }) .forEach { entry -> val jarEntry = JarEntry(entry.name) // Use the same constant as the fixed timestamps in normal copy actions jarEntry.time = ZipCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES newJarStream.putNextEntry(jarEntry) oldJar.getInputStream(entry).copyTo(newJarStream) } newJarStream.finish() } newFile.renameTo(originalOutput) } } junitbuild.java-toolchain-conventions.gradle.kts000066400000000000000000000025461455764576500337730ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlinimport org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension plugins { id("junitbuild.build-parameters") } project.pluginManager.withPlugin("java") { val defaultLanguageVersion = JavaLanguageVersion.of(17) val javaLanguageVersion = buildParameters.javaToolchainVersion.map { JavaLanguageVersion.of(it) }.getOrElse(defaultLanguageVersion) val extension = the() val javaToolchainService = the() extension.toolchain.languageVersion = javaLanguageVersion pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { configure { jvmToolchain { languageVersion = javaLanguageVersion } } } tasks.withType().configureEach { javaLauncher = javaToolchainService.launcherFor(extension.toolchain) } tasks.withType().configureEach { outputs.cacheIf { javaLanguageVersion == defaultLanguageVersion } doFirst { if (options.release.orNull == 8 && javaLanguageVersion.asInt() >= 20) { options.compilerArgs.add( "-Xlint:-options" // see https://github.com/junit-team/junit5/issues/3029 ) } } } tasks.withType().configureEach { javaLauncher.set(javaToolchainService.launcherFor { // Groovy does not yet support JDK 19, see https://issues.apache.org/jira/browse/GROOVY-10569 languageVersion = defaultLanguageVersion }) } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts000066400000000000000000000013541455764576500326700ustar00rootroot00000000000000plugins { `java-library` } val junit_4_12 by configurations.creatingResolvable { extendsFrom(configurations.testRuntimeClasspath.get()) } dependencies { junit_4_12("junit:junit") { version { strictly("4.12") } } pluginManager.withPlugin("junitbuild.osgi-conventions") { val junit4Osgi = requiredVersionFromLibs("junit4Osgi") "osgiVerification"("org.apache.servicemix.bundles:org.apache.servicemix.bundles.junit:${junit4Osgi}") } } tasks { val test_4_12 by registering(Test::class) { val test by testing.suites.existing(JvmTestSuite::class) testClassesDirs = files(test.map { it.sources.output.classesDirs }) classpath = files(test.map { it.sources.runtimeClasspath }) + junit_4_12 } check { dependsOn(test_4_12) } } junitbuild.kotlin-library-conventions.gradle.kts000066400000000000000000000012021455764576500340220ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlinimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("junitbuild.java-library-conventions") kotlin("jvm") } tasks.named("kotlinSourcesJar") { enabled = false } tasks.withType().configureEach { kotlinOptions { apiVersion = "1.3" languageVersion = "1.3" allWarningsAsErrors = false } } afterEvaluate { val extension = project.the() tasks { withType().configureEach { kotlinOptions.jvmTarget = extension.mainJavaVersion.toString() } named("compileTestKotlin") { kotlinOptions.jvmTarget = extension.testJavaVersion.toString() } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts000066400000000000000000000112601455764576500321050ustar00rootroot00000000000000import aQute.bnd.gradle.BundleTaskExtension import aQute.bnd.gradle.Resolve plugins { `java-library` } val importAPIGuardian = "org.apiguardian.*;resolution:=\"optional\"" val projectDescription = objects.property().convention(provider { project.description }) // This task enhances `jar` and `shadowJar` tasks with the bnd // `BundleTaskExtension` extension which allows for generating OSGi // metadata into the jar tasks.withType().matching { task: Jar -> task.name == "jar" || task.name == "shadowJar" }.all { // configure tasks eagerly as workaround for https://github.com/bndtools/bnd/issues/5695 extra["importAPIGuardian"] = importAPIGuardian extensions.create(BundleTaskExtension.NAME, this).apply { properties.set(projectDescription.map { mapOf("project.description" to it) }) // These are bnd instructions necessary for generating OSGi metadata. // We've generalized these so that they are widely applicable limiting // module configurations to special cases. setBnd( """ # Set the Bundle-SymbolicName to the archiveBaseName. # We don't use the archiveClassifier which Bnd will use # in the default Bundle-SymbolicName value. Bundle-SymbolicName: ${'$'}{task.archiveBaseName} # Set the Bundle-Name from the project description Bundle-Name: ${'$'}{project.description} # These are the general rules for package imports. Import-Package: \ ${importAPIGuardian},\ org.junit.platform.commons.logging;status=INTERNAL,\ kotlin.*;resolution:="optional",\ * # This tells bnd not to complain if a module doesn't actually import # the kotlin and apiguardian packages, but enough modules do to make it a default. -fixupmessages.kotlin.import: "Unused Import-Package instructions: \\[kotlin.*\\]";is:=ignore -fixupmessages.apiguardian.import: "Unused Import-Package instructions: \\[org.apiguardian.*\\]";is:=ignore # This tells bnd to ignore classes it finds in `META-INF/versions/` # because bnd doesn't yet support multi-release jars. -fixupmessages.wrong.dir: "Classes found in the wrong directory: \\{META-INF/versions/...";is:=ignore # Don't scan for Class.forName package imports. # See https://bnd.bndtools.org/instructions/noclassforname.html -noclassforname: true # Don't add all the extra headers bnd normally adds. # See https://bnd.bndtools.org/instructions/noextraheaders.html -noextraheaders: true # Don't add the Private-Package header. # See https://bnd.bndtools.org/instructions/removeheaders.html -removeheaders: Private-Package # Instruct the APIGuardianAnnotations how to operate. # See https://bnd.bndtools.org/instructions/export-apiguardian.html -export-apiguardian: *;version=${'$'}{versionmask;===;${'$'}{version_cleanup;${'$'}{task.archiveVersion}}} """ ) // Do the actual work putting OSGi stuff in the jar. doLast(buildAction()) } } // Bnd's Resolve task uses a properties file for its configuration. This // task writes out the properties necessary for it to verify the OSGi // metadata. val osgiProperties by tasks.registering(WriteProperties::class) { destinationFile = layout.buildDirectory.file("verifyOSGiProperties.bndrun") property("-standalone", true) project.extensions.getByType(JavaLibraryExtension::class.java).let { javaLibrary -> property("-runee", "JavaSE-${javaLibrary.mainJavaVersion}") } property("-runrequires", "osgi.identity;filter:='(osgi.identity=${project.name})'") property("-runsystempackages", "jdk.internal.misc,jdk.jfr,sun.misc") // API Guardian should be optional -> instruct resolver to ignore it // during resolution. Resolve should still pass. property("-runblacklist", "org.apiguardian.api") } val osgiVerification by configurations.creatingResolvable { extendsFrom(configurations.runtimeClasspath.get()) } // Bnd's Resolve task is what verifies that a jar can be used in OSGi and // that its metadata is valid. If the metadata is invalid this task will // fail. val verifyOSGi by tasks.registering(Resolve::class) { bndrun = osgiProperties.flatMap { it.destinationFile } outputBndrun = layout.buildDirectory.file("resolvedOSGiProperties.bndrun") isReportOptional = false // By default bnd will use jars found in: // 1. project.sourceSets.main.runtimeClasspath // 2. project.configurations.archives.artifacts.files // to validate the metadata. // This adds jars defined in `osgiVerification` also so that bnd // can use them to validate the metadata without causing those to // end up in the dependencies of those projects. bundles(osgiVerification) properties.empty() outputs.doNotCacheIf("https://github.com/bndtools/bnd/issues/5666") { true } } tasks.check { dependsOn(verifyOSGi) } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts000066400000000000000000000051711455764576500333140ustar00rootroot00000000000000plugins { `maven-publish` signing id("junitbuild.base-conventions") id("junitbuild.build-parameters") } val isSnapshot = project.version.toString().contains("SNAPSHOT") val jupiterProjects: List by rootProject val platformProjects: List by rootProject val vintageProjects: List by rootProject when (project) { in jupiterProjects -> { group = property("jupiterGroup")!! } in platformProjects -> { group = property("platformGroup")!! version = property("platformVersion")!! } in vintageProjects -> { group = property("vintageGroup")!! version = property("vintageVersion")!! } } // ensure project is built successfully before publishing it tasks.withType().configureEach { dependsOn(provider { val tempRepoName: String by rootProject if (repository.name != tempRepoName) { listOf(tasks.build) } else { emptyList() } }) } tasks.withType().configureEach { dependsOn(tasks.build) } val signArtifacts = buildParameters.publishing.signArtifacts.getOrElse(!(isSnapshot || buildParameters.ci)) signing { useGpgCmd() sign(publishing.publications) isRequired = signArtifacts } tasks.withType().configureEach { enabled = signArtifacts } publishing { publications { create("maven") { pom { name.set(provider { project.description ?: "${project.group}:${project.name}" }) url = "https://junit.org/junit5/" scm { connection = "scm:git:git://github.com/junit-team/junit5.git" developerConnection = "scm:git:git://github.com/junit-team/junit5.git" url = "https://github.com/junit-team/junit5" } licenses { license { val license: License by rootProject.extra name = license.name url = license.url.toString() } } developers { developer { id = "bechte" name = "Stefan Bechtold" email = "stefan.bechtold@me.com" } developer { id = "jlink" name = "Johannes Link" email = "business@johanneslink.net" } developer { id = "marcphilipp" name = "Marc Philipp" email = "mail@marcphilipp.de" } developer { id = "mmerdes" name = "Matthias Merdes" email = "matthias.merdes@heidelpay.com" } developer { id = "sbrannen" name = "Sam Brannen" email = "sam@sambrannen.com" } developer { id = "sormuras" name = "Christian Stein" email = "sormuras@gmail.com" } developer { id = "juliette-derancourt" name = "Juliette de Rancourt" email = "derancourt.juliette@gmail.com" } } } } } } junitbuild.settings-conventions.settings.gradle.kts000066400000000000000000000002311455764576500345600ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlinplugins { id("com.gradle.enterprise") id("com.gradle.common-custom-user-data-gradle-plugin") id("org.gradle.toolchains.foojay-resolver-convention") } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts000066400000000000000000000024521455764576500324340ustar00rootroot00000000000000import junitbuild.java.ModuleCompileOptions plugins { id("junitbuild.java-library-conventions") id("com.github.johnrengelman.shadow") } val shadowed by configurations.creatingResolvable configurations { listOf(apiElements, runtimeElements).forEach { it.configure { outgoing { artifacts.clear() artifact(tasks.shadowJar) { classifier = "" } } } } } sourceSets { main { compileClasspath += shadowed } test { runtimeClasspath += shadowed } } eclipse { classpath { plusConfigurations.add(shadowed) } } idea { module { scopes["PROVIDED"]!!["plus"]!!.add(shadowed) } } tasks { javadoc { classpath += shadowed } checkstyleMain { classpath += shadowed } shadowJar { configurations = listOf(shadowed) exclude("META-INF/maven/**") excludes.remove("module-info.class") archiveClassifier = "" } jar { dependsOn(shadowJar) enabled = false } named("codeCoverageClassesJar") { from(shadowJar.map { zipTree(it.archiveFile) }) exclude("**/shadow/**") } test { dependsOn(shadowJar) // in order to run the test against the shadowJar classpath -= sourceSets.main.get().output classpath += files(shadowJar.map { it.archiveFile }) } named("compileModule") { the().modulePath.from(shadowed) } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts000066400000000000000000000033761455764576500330310ustar00rootroot00000000000000import com.diffplug.gradle.spotless.SpotlessApply import com.diffplug.gradle.spotless.SpotlessCheck import com.diffplug.spotless.LineEnding plugins { id("com.diffplug.spotless") } val license: License by rootProject.extra spotless { format("misc") { target("*.gradle.kts", "buildSrc/**/*.gradle.kts", "*.gitignore") targetExclude("buildSrc/build/**") indentWithTabs() trimTrailingWhitespace() endWithNewline() } format("documentation") { target("*.adoc", "*.md", "src/**/*.adoc", "src/**/*.md") targetExclude("**/build", "**/target") trimTrailingWhitespace() endWithNewline() } pluginManager.withPlugin("java") { val configDir = rootProject.layout.projectDirectory.dir("gradle/config/eclipse") val importOrderConfigFile = configDir.file("junit-eclipse.importorder") val javaFormatterConfigFile = configDir.file("junit-eclipse-formatter-settings.xml") java { licenseHeaderFile(license.headerFile, "(package|import|open|module) ") importOrderFile(importOrderConfigFile) eclipse().configFile(javaFormatterConfigFile) trimTrailingWhitespace() endWithNewline() } } pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { kotlin { targetExclude("**/src/test/resources/**") ktlint(requiredVersionFromLibs("ktlint")) licenseHeaderFile(license.headerFile) trimTrailingWhitespace() endWithNewline() } } // https://github.com/diffplug/spotless/issues/1644 lineEndings = LineEnding.UNIX // or any other except GIT_ATTRIBUTES } tasks { withType().configureEach { notCompatibleWithConfigurationCache("https://github.com/diffplug/spotless/issues/644") } withType().configureEach { notCompatibleWithConfigurationCache("https://github.com/diffplug/spotless/issues/644") } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts000066400000000000000000000012131455764576500316120ustar00rootroot00000000000000import org.gradle.configurationcache.extensions.capitalized val tempRepoName by extra("temp") val tempRepoDir by extra { layout.buildDirectory.dir("repo").get().asFile } val clearTempRepoDir by tasks.registering { val dir = tempRepoDir doFirst { dir.deleteRecursively() } } subprojects { pluginManager.withPlugin("maven-publish") { configure { repositories { maven { name = tempRepoName url = uri(tempRepoDir) } } } tasks.withType().configureEach { if (name.endsWith("To${tempRepoName.capitalized()}Repository")) { dependsOn(clearTempRepoDir) } } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts000066400000000000000000000063711455764576500326300ustar00rootroot00000000000000import com.gradle.enterprise.gradleplugin.testretry.retry import com.gradle.enterprise.gradleplugin.testselection.internal.PredictiveTestSelectionExtensionInternal import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED import org.gradle.internal.os.OperatingSystem plugins { `java-library` id("junitbuild.build-parameters") } tasks.withType().configureEach { useJUnitPlatform { includeEngines("junit-jupiter") } include("**/*Test.class", "**/*Tests.class") testLogging { events = setOf(FAILED) exceptionFormat = FULL } retry { maxRetries = buildParameters.testing.retries.orElse(if (buildParameters.ci) 2 else 0) } distribution { enabled.convention(buildParameters.junit.develocity.testDistribution.enabled && (!buildParameters.ci || System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY").isNotBlank())) maxLocalExecutors = buildParameters.junit.develocity.testDistribution.maxLocalExecutors maxRemoteExecutors = buildParameters.junit.develocity.testDistribution.maxRemoteExecutors if (buildParameters.ci) { when { OperatingSystem.current().isLinux -> requirements.add("os=linux") OperatingSystem.current().isWindows -> requirements.add("os=windows") OperatingSystem.current().isMacOsX -> requirements.add("os=macos") } } } predictiveSelection { enabled = buildParameters.junit.develocity.predictiveTestSelection.enabled // Ensure PTS works when publishing Build Scans to scans.gradle.com this as PredictiveTestSelectionExtensionInternal server = uri("https://ge.junit.org") } systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") // Required until ASM officially supports the JDK 14 systemProperty("net.bytebuddy.experimental", true) if (buildParameters.testing.enableJFR) { jvmArgs( "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints", "-XX:StartFlightRecording=filename=${reports.junitXml.outputLocation.get()},dumponexit=true,settings=profile.jfc", "-XX:FlightRecorderOptions=stackdepth=1024" ) } // Track OS as input so that tests are executed on all configured operating systems on CI trackOperationSystemAsInput() // Avoid passing unnecessary environment variables to the JVM (from GitHub Actions) if (buildParameters.ci) { environment.remove("RUNNER_TEMP") environment.remove("GITHUB_ACTION") } jvmArgumentProviders += CommandLineArgumentProvider { listOf( "-Djunit.platform.reporting.open.xml.enabled=true", "-Djunit.platform.reporting.output.dir=${reports.junitXml.outputLocation.get().asFile.absolutePath}" ) } } dependencies { testImplementation(dependencyFromLibs("assertj")) testImplementation(dependencyFromLibs("mockito")) testImplementation(dependencyFromLibs("testingAnnotations")) if (!project.name.startsWith("junit-jupiter")) { testImplementation(project(":junit-jupiter")) } testRuntimeOnly(project(":junit-platform-engine")) testRuntimeOnly(project(":junit-platform-jfr")) testRuntimeOnly(project(":junit-platform-reporting")) testRuntimeOnly(bundleFromLibs("log4j")) testRuntimeOnly(dependencyFromLibs("openTestReporting-events")) { because("it's required to run tests via IntelliJ which does not consumed the shadowed jar of junit-platform-reporting") } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/000077500000000000000000000000001455764576500246225ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/exec/000077500000000000000000000000001455764576500255465ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/exec/CaptureJavaExecOutput.kt000066400000000000000000000031721455764576500323440ustar00rootroot00000000000000package junitbuild.exec import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Input import org.gradle.api.tasks.Nested import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction import org.gradle.process.CommandLineArgumentProvider import org.gradle.process.ExecOperations import java.nio.file.Files import javax.inject.Inject @CacheableTask abstract class CaptureJavaExecOutput @Inject constructor(private val execOperations: ExecOperations) : DefaultTask() { @get:Classpath abstract val classpath: ConfigurableFileCollection @get:Input abstract val mainClass: Property @get:Input abstract val args: ListProperty @get:Nested val jvmArgumentProviders = mutableListOf() @get:OutputFile abstract val outputFile: RegularFileProperty @TaskAction fun execute() { val outputFile = outputFile.get().asFile.toPath() Files.newOutputStream(outputFile).use { out -> execOperations.javaexec { classpath = this@CaptureJavaExecOutput.classpath mainClass.set(this@CaptureJavaExecOutput.mainClass) args = this@CaptureJavaExecOutput.args.get() jvmArgumentProviders.addAll(this@CaptureJavaExecOutput.jvmArgumentProviders) standardOutput = out } } } } ClasspathSystemPropertyProvider.kt000066400000000000000000000005771455764576500344470ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/execpackage junitbuild.exec import org.gradle.api.file.FileCollection import org.gradle.api.tasks.Classpath import org.gradle.process.CommandLineArgumentProvider class ClasspathSystemPropertyProvider(private val propertyName: String, @get:Classpath val files: FileCollection) : CommandLineArgumentProvider { override fun asArguments() = listOf("-D$propertyName=${files.asPath}") } GenerateStandaloneConsoleLauncherShadowedArtifactsFile.kt000066400000000000000000000023431455764576500407210ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/execpackage junitbuild.exec import org.gradle.api.DefaultTask import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.RegularFileProperty import org.gradle.api.file.RelativePath import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction import javax.inject.Inject @CacheableTask abstract class GenerateStandaloneConsoleLauncherShadowedArtifactsFile @Inject constructor( private val fileSystem: FileSystemOperations, private val archives: ArchiveOperations ) : DefaultTask() { @get:Classpath abstract val inputJar: RegularFileProperty @get:OutputFile abstract val outputFile: RegularFileProperty @TaskAction fun execute() { fileSystem.copy { from(archives.zipTree(inputJar)) { include("META-INF/shadowed-artifacts") includeEmptyDirs = false eachFile { relativePath = RelativePath(true, outputFile.get().asFile.name) } filter { line -> "- `${line}`" } } into(outputFile.get().asFile.parentFile) } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt000066400000000000000000000065501455764576500316650ustar00rootroot00000000000000package junitbuild.exec import org.apache.tools.ant.types.Commandline import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* import org.gradle.api.tasks.options.Option import org.gradle.jvm.toolchain.JavaLauncher import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.the import org.gradle.process.CommandLineArgumentProvider import org.gradle.process.ExecOperations import trackOperationSystemAsInput import java.io.ByteArrayOutputStream import java.util.* import javax.inject.Inject @CacheableTask abstract class RunConsoleLauncher @Inject constructor(private val execOperations: ExecOperations) : DefaultTask() { @get:Classpath abstract val runtimeClasspath: ConfigurableFileCollection @get:Input abstract val args: ListProperty @get:Nested abstract val argumentProviders: ListProperty @get:Input abstract val commandLineArgs: ListProperty @get:Nested abstract val javaLauncher: Property @get:Internal abstract val debugging: Property @get:Internal abstract val hideOutput: Property init { runtimeClasspath.from(project.the()["test"].runtimeClasspath) javaLauncher.set(project.the().launcherFor(project.the().toolchain)) debugging.convention(false) commandLineArgs.convention(emptyList()) outputs.cacheIf { !debugging.get() } outputs.upToDateWhen { !debugging.get() } hideOutput.convention(debugging.map { !it }) trackOperationSystemAsInput() } @TaskAction fun execute() { val output = ByteArrayOutputStream() val result = execOperations.javaexec { executable = javaLauncher.get().executablePath.asFile.absolutePath classpath = runtimeClasspath mainClass.set("org.junit.platform.console.ConsoleLauncher") args(this@RunConsoleLauncher.args.get()) args(this@RunConsoleLauncher.commandLineArgs.get()) argumentProviders.addAll(this@RunConsoleLauncher.argumentProviders.get()) systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") debug = debugging.get() if (hideOutput.get()) { standardOutput = output errorOutput = output } isIgnoreExitValue = true } if (result.exitValue != 0 && hideOutput.get()) { System.out.write(output.toByteArray()) System.out.flush() } result.rethrowFailure().assertNormalExitValue() } @Suppress("unused") @Option(option = "args", description = "Additional command line arguments for the console launcher") fun setCliArgs(args: String) { commandLineArgs.set(Commandline.translateCommandline(args).toList()) } @Suppress("unused") @Option( option = "debug-jvm", description = "Enable debugging. The process is started suspended and listening on port 5005." ) fun setDebug(enabled: Boolean) { debugging.set(enabled) } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/000077500000000000000000000000001455764576500255435ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/ExecJarAction.kt000066400000000000000000000013411455764576500305610ustar00rootroot00000000000000package junitbuild.java import org.gradle.api.Action import org.gradle.api.Task import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.jvm.toolchain.JavaLauncher import org.gradle.process.ExecOperations import javax.inject.Inject abstract class ExecJarAction @Inject constructor(private val operations: ExecOperations): Action { abstract val javaLauncher: Property abstract val args: ListProperty override fun execute(t: Task) { operations.exec { executable = javaLauncher.get() .metadata.installationPath.file("bin/jar").asFile.absolutePath args = this@ExecJarAction.args.get() } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt000066400000000000000000000002601455764576500322130ustar00rootroot00000000000000package junitbuild.java import org.gradle.api.file.ConfigurableFileCollection abstract class ModuleCompileOptions { abstract val modulePath: ConfigurableFileCollection } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt000066400000000000000000000023071455764576500333650ustar00rootroot00000000000000package junitbuild.java import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.Directory import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.process.CommandLineArgumentProvider import javax.inject.Inject abstract class ModulePathArgumentProvider @Inject constructor(project: Project, combinedModuleSourceDir: Provider, modularProjects: List) : CommandLineArgumentProvider, Named { @get:CompileClasspath abstract val modulePath: ConfigurableFileCollection @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) abstract val moduleSourceDirs: ConfigurableFileCollection init { modularProjects.forEach { if (it == project) moduleSourceDirs.from(combinedModuleSourceDir) else moduleSourceDirs.from(project.files("${it.projectDir}/src/module")) } } override fun asArguments() = listOf( "--module-path", modulePath.asPath, "--module-source-path", moduleSourceDirs.asPath ) @Internal override fun getName() = "module-path" } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt000066400000000000000000000027541455764576500335360ustar00rootroot00000000000000package junitbuild.java import javaModuleName import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.provider.Property import org.gradle.api.tasks.* import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.the import org.gradle.process.CommandLineArgumentProvider import javax.inject.Inject abstract class PatchModuleArgumentProvider @Inject constructor(compiledProject: Project, patchModuleProject: Project) : CommandLineArgumentProvider, Named { @get:Input abstract val module: Property @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) abstract val patch: ConfigurableFileCollection init { module.convention(patchModuleProject.javaModuleName) patch.from(compiledProject.provider { if (patchModuleProject == compiledProject) compiledProject.files(compiledProject.the().matching { it.name.startsWith("main") } .map { it.output }) else patchModuleProject.files(patchModuleProject.the()["main"].java.srcDirs) }) } override fun asArguments(): List { val path = patch.filter { it.exists() }.asPath if (path.isEmpty()) { return emptyList() } return listOf("--patch-module", "${module.get()}=$path") } @Internal override fun getName() = "patch-module(${module.get()})" } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt000066400000000000000000000021101455764576500316300ustar00rootroot00000000000000package junitbuild.java import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ModuleVersionIdentifier import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Provider import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction abstract class WriteArtifactsFile : DefaultTask() { @get:OutputFile abstract val outputFile: RegularFileProperty @get:Input abstract val moduleVersions: SetProperty fun from(configuration: Provider) { moduleVersions.addAll(configuration.map { it.resolvedConfiguration.resolvedArtifacts.map { it.moduleVersion.id } }) } @TaskAction fun writeFile() { outputFile.get().asFile.printWriter().use { out -> moduleVersions.get() .map { "${it.group}:${it.name}:${it.version}" } .sorted() .forEach(out::println) } } } junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/000077500000000000000000000000001455764576500262315ustar00rootroot00000000000000ModuleSpecificJavadocFileOption.kt000066400000000000000000000015431455764576500346710ustar00rootroot00000000000000junit5-r5.10.2/gradle/plugins/common/src/main/kotlin/junitbuild/javadocpackage junitbuild.javadoc import org.gradle.external.javadoc.JavadocOptionFileOption import org.gradle.external.javadoc.internal.JavadocOptionFileWriterContext class ModuleSpecificJavadocFileOption(private val option: String, private var valuePerModule: Map) : JavadocOptionFileOption> { override fun getOption() = option override fun getValue() = valuePerModule override fun setValue(value: Map) { this.valuePerModule = value } override fun write(writerContext: JavadocOptionFileWriterContext) { valuePerModule.forEach { (moduleName, value) -> writerContext .writeOptionHeader(option) .write(moduleName) .write("=") .write(value) .newLine() } } } junit5-r5.10.2/gradle/plugins/settings.gradle.kts000066400000000000000000000010451455764576500217660ustar00rootroot00000000000000val expectedJavaVersion = JavaVersion.VERSION_17 val actualJavaVersion = JavaVersion.current() require(actualJavaVersion == expectedJavaVersion) { "The JUnit 5 build must be executed with Java ${expectedJavaVersion.majorVersion}. Currently executing with Java ${actualJavaVersion.majorVersion}." } dependencyResolutionManagement { versionCatalogs { create("libs") { from(files("../libs.versions.toml")) } } } rootProject.name = "plugins" include("build-parameters") include("common") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") junit5-r5.10.2/gradle/scripts/000077500000000000000000000000001455764576500161545ustar00rootroot00000000000000junit5-r5.10.2/gradle/scripts/checkBuildReproducibility.sh000077500000000000000000000011311455764576500236360ustar00rootroot00000000000000#!/bin/bash -e rm -rf checksums* export SOURCE_DATE_EPOCH=$(date +%s) function calculate_checksums() { OUTPUT=$1 ./gradlew \ --configuration-cache \ --no-build-cache \ -Porg.gradle.java.installations.auto-download=false \ -Dscan.tag.Reproducibility \ clean \ assemble find . -name '*.jar' \ | grep '/build/libs/' \ | grep --invert-match 'javadoc' \ | sort \ | xargs sha256sum > "${OUTPUT}" } calculate_checksums checksums-1.txt calculate_checksums checksums-2.txt diff checksums-1.txt checksums-2.txt junit5-r5.10.2/junit-bom/000077500000000000000000000000001455764576500151335ustar00rootroot00000000000000junit5-r5.10.2/junit-bom/README.md000066400000000000000000000007461455764576500164210ustar00rootroot00000000000000# JUnit Bill of Materials (BOM) This module provides a Bill of Materials POM to ease dependency management using [Maven] or [Gradle]. Please refer to the [User Guide] for details. [Maven]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies [Gradle]: https://docs.gradle.org/current/userguide/platforms.html#sub:bom_import [User Guide]: https://junit.org/junit5/docs/current/user-guide/#dependency-metadata-junit-bom junit5-r5.10.2/junit-bom/junit-bom.gradle.kts000066400000000000000000000024331455764576500210210ustar00rootroot00000000000000plugins { `java-platform` id("junitbuild.publishing-conventions") } description = "${rootProject.description} (Bill of Materials)" dependencies { constraints { val mavenizedProjects: List by rootProject.extra mavenizedProjects.sorted() .filter { it.name != "junit-platform-console-standalone" } .forEach { api("${it.group}:${it.name}:${it.version}") } } } publishing.publications.named("maven") { from(components["javaPlatform"]) pom { description = "This Bill of Materials POM can be used to ease dependency management " + "when referencing multiple JUnit artifacts using Gradle or Maven." withXml { val filteredContent = asString().replace("\\s*compile".toRegex(), "") asString().clear().append(filteredContent) } } } tasks.withType().configureEach { doLast { val xml = destination.readText() require(xml.indexOf("") == xml.lastIndexOf("")) { "BOM must contain exactly one element but contained multiple:\n$destination" } require(xml.contains("")) { "BOM must contain a element:\n$destination" } require(!xml.contains("")) { "BOM must not contain elements:\n$destination" } } } junit5-r5.10.2/junit-jupiter-api/000077500000000000000000000000001455764576500166075ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/junit-jupiter-api.gradle.kts000066400000000000000000000013411455764576500241460ustar00rootroot00000000000000plugins { id("junitbuild.kotlin-library-conventions") `java-test-fixtures` } description = "JUnit Jupiter API" dependencies { api(platform(projects.junitBom)) api(libs.opentest4j) api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) compileOnly(kotlin("stdlib")) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks { jar { bundle { val version = project.version bnd(""" Require-Capability:\ org.junit.platform.engine;\ filter:='(&(org.junit.platform.engine=junit-jupiter)(version>=${'$'}{version_cleanup;${version}})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;${version}}})))';\ effective:=active """) } } } junit5-r5.10.2/junit-jupiter-api/src/000077500000000000000000000000001455764576500173765ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/000077500000000000000000000000001455764576500203225ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/000077500000000000000000000000001455764576500212435ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/000077500000000000000000000000001455764576500220325ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/000077500000000000000000000000001455764576500231635ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/000077500000000000000000000000001455764576500246455ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/000077500000000000000000000000001455764576500254165ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterAll.java000066400000000000000000000105311455764576500277530ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @AfterAll} is used to signal that the annotated method should be * executed after all tests in the current test class. * *

In contrast to {@link AfterEach @AfterEach} methods, {@code @AfterAll} * methods are only executed once for a given test class. * *

Method Signatures

* *

{@code @AfterAll} methods must have a {@code void} return type and must be * {@code static} by default. Consequently, {@code @AfterAll} methods are not * supported in {@link Nested @Nested} test classes or as interface default * methods unless the test class is annotated with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * However, beginning with Java 16 {@code @AfterAll} methods may be declared as * {@code static} in {@link Nested @Nested} test classes, and the * {@code Lifecycle.PER_CLASS} restriction no longer applies. {@code @AfterAll} * methods may optionally declare parameters to be resolved by * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolvers}. * *

Using {@code private} visibility for {@code @AfterAll} methods is * strongly discouraged and will be disallowed in a future release. * *

Inheritance and Execution Order

* *

{@code @AfterAll} methods are inherited from superclasses as long as * they are not hidden (default mode with {@code static} modifier), * overridden, or superseded (i.e., replaced based on * signature only, irrespective of Java's visibility rules). Furthermore, * {@code @AfterAll} methods from superclasses will be executed before * {@code @AfterAll} methods in subclasses. * *

Similarly, {@code @AfterAll} methods declared in an interface are * inherited as long as they are not hidden or overridden, * and {@code @AfterAll} methods from an interface will be executed after * {@code @AfterAll} methods in the class that implements the interface. * *

JUnit Jupiter does not guarantee the execution order of multiple * {@code @AfterAll} methods that are declared within a single test class or * test interface. While it may at times appear that these methods are invoked * in alphabetical order, they are in fact sorted using an algorithm that is * deterministic but intentionally non-obvious. * *

In addition, {@code @AfterAll} methods are in no way linked to * {@code @BeforeAll} methods. Consequently, there are no guarantees with regard * to their wrapping behavior. For example, given two * {@code @BeforeAll} methods {@code createA()} and {@code createB()} as well as * two {@code @AfterAll} methods {@code destroyA()} and {@code destroyB()}, the * order in which the {@code @BeforeAll} methods are executed (e.g. * {@code createA()} before {@code createB()}) does not imply any order for the * seemingly corresponding {@code @AfterAll} methods. In other words, * {@code destroyA()} might be called before or after * {@code destroyB()}. The JUnit Team therefore recommends that developers * declare at most one {@code @BeforeAll} method and at most one * {@code @AfterAll} method per test class or test interface unless there are no * dependencies between the {@code @BeforeAll} methods or between the * {@code @AfterAll} methods. * *

Composition

* *

{@code @AfterAll} may be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @AfterAll}. * * @since 5.0 * @see BeforeAll * @see BeforeEach * @see AfterEach * @see Test * @see TestFactory * @see TestInstance */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface AfterAll { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterEach.java000066400000000000000000000074321455764576500301110ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @AfterEach} is used to signal that the annotated method should be * executed after each {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, * and {@code @TestTemplate} method in the current test class. * *

Method Signatures

* *

{@code @AfterEach} methods must have a {@code void} return type and must * not be {@code static}. Using {@code private} visibility is strongly * discouraged and will be disallowed in a future release. * They may optionally declare parameters to be resolved by * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolvers}. * *

Inheritance and Execution Order

* *

{@code @AfterEach} methods are inherited from superclasses as long as they * are not overridden or superseded (i.e., replaced based on * signature only, irrespective of Java's visibility rules). Furthermore, * {@code @AfterEach} methods from superclasses will be executed after * {@code @AfterEach} methods in subclasses. * *

Similarly, {@code @AfterEach} methods declared as interface default * methods are inherited as long as they are not overridden, and * {@code @AfterEach} default methods will be executed after {@code @AfterEach} * methods in the class that implements the interface. * *

JUnit Jupiter does not guarantee the execution order of multiple * {@code @AfterEach} methods that are declared within a single test class or * test interface. While it may at times appear that these methods are invoked * in alphabetical order, they are in fact sorted using an algorithm that is * deterministic but intentionally non-obvious. * *

In addition, {@code @AfterEach} methods are in no way linked to * {@code @BeforeEach} methods. Consequently, there are no guarantees with * regard to their wrapping behavior. For example, given two * {@code @BeforeEach} methods {@code createA()} and {@code createB()} as well * as two {@code @AfterEach} methods {@code destroyA()} and {@code destroyB()}, * the order in which the {@code @BeforeEach} methods are executed (e.g. * {@code createA()} before {@code createB()}) does not imply any order for the * seemingly corresponding {@code @AfterEach} methods. In other words, * {@code destroyA()} might be called before or after * {@code destroyB()}. The JUnit Team therefore recommends that developers * declare at most one {@code @BeforeEach} method and at most one * {@code @AfterEach} method per test class or test interface unless there are * no dependencies between the {@code @BeforeEach} methods or between the * {@code @AfterEach} methods. * *

Composition

* *

{@code @AfterEach} may be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @AfterEach}. * * @since 5.0 * @see BeforeEach * @see BeforeAll * @see AfterAll * @see Test * @see RepeatedTest * @see TestFactory * @see TestTemplate */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface AfterEach { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java000066400000000000000000000050511455764576500301540ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.MultipleFailuresError; /** * {@code AssertAll} is a collection of utility methods that support asserting * multiple conditions in tests at once. * * @since 5.0 */ class AssertAll { private AssertAll() { /* no-op */ } static void assertAll(Executable... executables) { assertAll(null, executables); } static void assertAll(String heading, Executable... executables) { Preconditions.notEmpty(executables, "executables array must not be null or empty"); Preconditions.containsNoNullElements(executables, "individual executables must not be null"); assertAll(heading, Arrays.stream(executables)); } static void assertAll(Collection executables) { assertAll(null, executables); } static void assertAll(String heading, Collection executables) { Preconditions.notNull(executables, "executables collection must not be null"); Preconditions.containsNoNullElements(executables, "individual executables must not be null"); assertAll(heading, executables.stream()); } static void assertAll(Stream executables) { assertAll(null, executables); } static void assertAll(String heading, Stream executables) { Preconditions.notNull(executables, "executables stream must not be null"); List failures = executables // .map(executable -> { Preconditions.notNull(executable, "individual executables must not be null"); try { executable.execute(); return null; } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); return t; } }) // .filter(Objects::nonNull) // .collect(Collectors.toList()); if (!failures.isEmpty()) { MultipleFailuresError multipleFailuresError = new MultipleFailuresError(heading, failures); failures.forEach(multipleFailuresError::addSuppressed); throw multipleFailuresError; } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java000066400000000000000000000363611455764576500317050ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.formatIndexes; import static org.junit.platform.commons.util.ReflectionUtils.isArray; import java.util.ArrayDeque; import java.util.Deque; import java.util.Objects; import java.util.function.Supplier; /** * {@code AssertArrayEquals} is a collection of utility methods that support asserting * array equality in tests. * * @since 5.0 */ class AssertArrayEquals { private AssertArrayEquals() { /* no-op */ } static void assertArrayEquals(boolean[] expected, boolean[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(boolean[] expected, boolean[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(boolean[] expected, boolean[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(char[] expected, char[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(char[] expected, char[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(char[] expected, char[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(byte[] expected, byte[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(byte[] expected, byte[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(byte[] expected, byte[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(short[] expected, short[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(short[] expected, short[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(short[] expected, short[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(int[] expected, int[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(int[] expected, int[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(int[] expected, int[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(long[] expected, long[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(long[] expected, long[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(long[] expected, long[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(float[] expected, float[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(float[] expected, float[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(float[] expected, float[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(float[] expected, float[] actual, float delta) { assertArrayEquals(expected, actual, delta, (String) null); } static void assertArrayEquals(float[] expected, float[] actual, float delta, String message) { assertArrayEquals(expected, actual, delta, null, message); } static void assertArrayEquals(float[] expected, float[] actual, float delta, Supplier messageSupplier) { assertArrayEquals(expected, actual, delta, null, messageSupplier); } static void assertArrayEquals(double[] expected, double[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(double[] expected, double[] actual, String message) { assertArrayEquals(expected, actual, null, message); } static void assertArrayEquals(double[] expected, double[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } static void assertArrayEquals(double[] expected, double[] actual, double delta) { assertArrayEquals(expected, actual, delta, (String) null); } static void assertArrayEquals(double[] expected, double[] actual, double delta, String message) { assertArrayEquals(expected, actual, delta, null, message); } static void assertArrayEquals(double[] expected, double[] actual, double delta, Supplier messageSupplier) { assertArrayEquals(expected, actual, delta, null, messageSupplier); } static void assertArrayEquals(Object[] expected, Object[] actual) { assertArrayEquals(expected, actual, (String) null); } static void assertArrayEquals(Object[] expected, Object[] actual, String message) { assertArrayEquals(expected, actual, new ArrayDeque<>(), message); } static void assertArrayEquals(Object[] expected, Object[] actual, Supplier messageSupplier) { assertArrayEquals(expected, actual, new ArrayDeque<>(), messageSupplier); } private static void assertArrayEquals(boolean[] expected, boolean[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(char[] expected, char[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(byte[] expected, byte[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(short[] expected, short[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(int[] expected, int[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(long[] expected, long[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(float[] expected, float[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (!AssertionUtils.floatsAreEqual(expected[i], actual[i])) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(float[] expected, float[] actual, float delta, Deque indexes, Object messageOrSupplier) { AssertionUtils.assertValidDelta(delta); if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (!AssertionUtils.floatsAreEqual(expected[i], actual[i], delta)) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(double[] expected, double[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (!AssertionUtils.doublesAreEqual(expected[i], actual[i])) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(double[] expected, double[] actual, double delta, Deque indexes, Object messageOrSupplier) { AssertionUtils.assertValidDelta(delta); if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { if (!AssertionUtils.doublesAreEqual(expected[i], actual[i], delta)) { failArraysNotEqual(expected[i], actual[i], nullSafeIndexes(indexes, i), messageOrSupplier); } } } private static void assertArrayEquals(Object[] expected, Object[] actual, Deque indexes, Object messageOrSupplier) { if (expected == actual) { return; } assertArraysNotNull(expected, actual, indexes, messageOrSupplier); assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { Object expectedElement = expected[i]; Object actualElement = actual[i]; if (expectedElement == actualElement) { continue; } indexes.addLast(i); assertArrayElementsEqual(expectedElement, actualElement, indexes, messageOrSupplier); indexes.removeLast(); } } private static void assertArrayElementsEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { if (expected instanceof Object[] && actual instanceof Object[]) { assertArrayEquals((Object[]) expected, (Object[]) actual, indexes, messageOrSupplier); } else if (expected instanceof byte[] && actual instanceof byte[]) { assertArrayEquals((byte[]) expected, (byte[]) actual, indexes, messageOrSupplier); } else if (expected instanceof short[] && actual instanceof short[]) { assertArrayEquals((short[]) expected, (short[]) actual, indexes, messageOrSupplier); } else if (expected instanceof int[] && actual instanceof int[]) { assertArrayEquals((int[]) expected, (int[]) actual, indexes, messageOrSupplier); } else if (expected instanceof long[] && actual instanceof long[]) { assertArrayEquals((long[]) expected, (long[]) actual, indexes, messageOrSupplier); } else if (expected instanceof char[] && actual instanceof char[]) { assertArrayEquals((char[]) expected, (char[]) actual, indexes, messageOrSupplier); } else if (expected instanceof float[] && actual instanceof float[]) { assertArrayEquals((float[]) expected, (float[]) actual, indexes, messageOrSupplier); } else if (expected instanceof double[] && actual instanceof double[]) { assertArrayEquals((double[]) expected, (double[]) actual, indexes, messageOrSupplier); } else if (expected instanceof boolean[] && actual instanceof boolean[]) { assertArrayEquals((boolean[]) expected, (boolean[]) actual, indexes, messageOrSupplier); } else if (!Objects.equals(expected, actual)) { if (expected == null && isArray(actual)) { failExpectedArrayIsNull(indexes, messageOrSupplier); } else if (isArray(expected) && actual == null) { failActualArrayIsNull(indexes, messageOrSupplier); } else { failArraysNotEqual(expected, actual, indexes, messageOrSupplier); } } } private static void assertArraysNotNull(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { if (expected == null) { failExpectedArrayIsNull(indexes, messageOrSupplier); } if (actual == null) { failActualArrayIsNull(indexes, messageOrSupplier); } } private static void failExpectedArrayIsNull(Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected array was " + formatIndexes(indexes)) // .buildAndThrow(); } private static void failActualArrayIsNull(Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("actual array was " + formatIndexes(indexes)) // .buildAndThrow(); } private static void assertArraysHaveSameLength(int expected, int actual, Deque indexes, Object messageOrSupplier) { if (expected != actual) { assertionFailure() // .message(messageOrSupplier) // .reason("array lengths differ" + formatIndexes(indexes)) // .expected(expected) // .actual(actual) // .buildAndThrow(); } } private static void failArraysNotEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("array contents differ" + formatIndexes(indexes)) // .expected(expected) // .actual(actual) // .buildAndThrow(); } private static Deque nullSafeIndexes(Deque indexes, int newIndex) { Deque result = (indexes != null ? indexes : new ArrayDeque<>()); result.addLast(newIndex); return result; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java000066400000000000000000000053621455764576500320500ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.AssertionFailedError; /** * {@code AssertDoesNotThrow} is a collection of utility methods that support * explicitly asserting that a given code block does not throw an exception. * * @since 5.2 */ class AssertDoesNotThrow { private AssertDoesNotThrow() { /* no-op */ } static void assertDoesNotThrow(Executable executable) { assertDoesNotThrow(executable, (Object) null); } static void assertDoesNotThrow(Executable executable, String message) { assertDoesNotThrow(executable, (Object) message); } static void assertDoesNotThrow(Executable executable, Supplier messageSupplier) { assertDoesNotThrow(executable, (Object) messageSupplier); } private static void assertDoesNotThrow(Executable executable, Object messageOrSupplier) { try { executable.execute(); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); throw createAssertionFailedError(messageOrSupplier, t); } } static T assertDoesNotThrow(ThrowingSupplier supplier) { return assertDoesNotThrow(supplier, (Object) null); } static T assertDoesNotThrow(ThrowingSupplier supplier, String message) { return assertDoesNotThrow(supplier, (Object) message); } static T assertDoesNotThrow(ThrowingSupplier supplier, Supplier messageSupplier) { return assertDoesNotThrow(supplier, (Object) messageSupplier); } private static T assertDoesNotThrow(ThrowingSupplier supplier, Object messageOrSupplier) { try { return supplier.get(); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); throw createAssertionFailedError(messageOrSupplier, t); } } private static AssertionFailedError createAssertionFailedError(Object messageOrSupplier, Throwable t) { return assertionFailure() // .message(messageOrSupplier) // .reason("Unexpected exception thrown: " + t.getClass().getName() + buildSuffix(t.getMessage())) // .cause(t) // .build(); } private static String buildSuffix(String message) { return StringUtils.isNotBlank(message) ? ": " + message : ""; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java000066400000000000000000000133121455764576500306750ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.doublesAreEqual; import static org.junit.jupiter.api.AssertionUtils.floatsAreEqual; import static org.junit.jupiter.api.AssertionUtils.objectsAreEqual; import java.util.function.Supplier; /** * {@code AssertEquals} is a collection of utility methods that support asserting * equality on objects and primitives in tests. * * @since 5.0 */ class AssertEquals { private AssertEquals() { /* no-op */ } static void assertEquals(byte expected, byte actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(byte expected, byte actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } static void assertEquals(byte expected, byte actual, Supplier messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(char expected, char actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(char expected, char actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } static void assertEquals(char expected, char actual, Supplier messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(double expected, double actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(double expected, double actual, String message) { if (!doublesAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } static void assertEquals(double expected, double actual, Supplier messageSupplier) { if (!doublesAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(double expected, double actual, double delta) { assertEquals(expected, actual, delta, (String) null); } static void assertEquals(double expected, double actual, double delta, String message) { if (!doublesAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, message); } } static void assertEquals(double expected, double actual, double delta, Supplier messageSupplier) { if (!doublesAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(float expected, float actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(float expected, float actual, String message) { if (!floatsAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } static void assertEquals(float expected, float actual, Supplier messageSupplier) { if (!floatsAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(float expected, float actual, float delta) { assertEquals(expected, actual, delta, (String) null); } static void assertEquals(float expected, float actual, float delta, String message) { if (!floatsAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, message); } } static void assertEquals(float expected, float actual, float delta, Supplier messageSupplier) { if (!floatsAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(short expected, short actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(short expected, short actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } static void assertEquals(short expected, short actual, Supplier messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(int expected, int actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(int expected, int actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } static void assertEquals(int expected, int actual, Supplier messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(long expected, long actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(long expected, long actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } static void assertEquals(long expected, long actual, Supplier messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } static void assertEquals(Object expected, Object actual) { assertEquals(expected, actual, (String) null); } static void assertEquals(Object expected, Object actual, String message) { if (!objectsAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } static void assertEquals(Object expected, Object actual, Supplier messageSupplier) { if (!objectsAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } } private static void failNotEqual(Object expected, Object actual, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(expected) // .actual(actual) // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java000066400000000000000000000032041455764576500304740ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.BooleanSupplier; import java.util.function.Supplier; /** * {@code AssertFalse} is a collection of utility methods that support asserting * {@code false} in tests. * * @since 5.0 */ class AssertFalse { private AssertFalse() { /* no-op */ } static void assertFalse(boolean condition) { assertFalse(condition, (String) null); } static void assertFalse(boolean condition, String message) { if (condition) { failNotFalse(message); } } static void assertFalse(boolean condition, Supplier messageSupplier) { if (condition) { failNotFalse(messageSupplier); } } static void assertFalse(BooleanSupplier booleanSupplier) { assertFalse(booleanSupplier.getAsBoolean(), (String) null); } static void assertFalse(BooleanSupplier booleanSupplier, String message) { assertFalse(booleanSupplier.getAsBoolean(), message); } static void assertFalse(BooleanSupplier booleanSupplier, Supplier messageSupplier) { assertFalse(booleanSupplier.getAsBoolean(), messageSupplier); } private static void failNotFalse(Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(false) // .actual(true) // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java000066400000000000000000000033231455764576500314750ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; /** * {@code AssertInstanceOf} is a collection of utility methods that support * asserting that an object is of an expected type — in other words, if it * can be assigned to the expected type. * * @since 5.8 */ class AssertInstanceOf { private AssertInstanceOf() { /* no-op */ } static T assertInstanceOf(Class expectedType, Object actualValue) { return assertInstanceOf(expectedType, actualValue, (Object) null); } static T assertInstanceOf(Class expectedType, Object actualValue, String message) { return assertInstanceOf(expectedType, actualValue, (Object) message); } static T assertInstanceOf(Class expectedType, Object actualValue, Supplier messageSupplier) { return assertInstanceOf(expectedType, actualValue, (Object) messageSupplier); } private static T assertInstanceOf(Class expectedType, Object actualValue, Object messageOrSupplier) { if (!expectedType.isInstance(actualValue)) { assertionFailure() // .message(messageOrSupplier) // .reason(actualValue == null ? "Unexpected null value" : "Unexpected type") // .expected(expectedType) // .actual(actualValue == null ? null : actualValue.getClass()) // .buildAndThrow(); } return expectedType.cast(actualValue); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java000066400000000000000000000153011455764576500323450ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.formatIndexes; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; /** * {@code AssertIterable} is a collection of utility methods that support asserting * Iterable equality in tests. * * @since 5.0 */ class AssertIterableEquals { private AssertIterableEquals() { /* no-op */ } static void assertIterableEquals(Iterable expected, Iterable actual) { assertIterableEquals(expected, actual, (String) null); } static void assertIterableEquals(Iterable expected, Iterable actual, String message) { assertIterableEquals(expected, actual, new ArrayDeque<>(), message); } static void assertIterableEquals(Iterable expected, Iterable actual, Supplier messageSupplier) { assertIterableEquals(expected, actual, new ArrayDeque<>(), messageSupplier); } private static void assertIterableEquals(Iterable expected, Iterable actual, Deque indexes, Object messageOrSupplier) { assertIterableEquals(expected, actual, indexes, messageOrSupplier, new LinkedHashMap<>()); } private static void assertIterableEquals(Iterable expected, Iterable actual, Deque indexes, Object messageOrSupplier, Map investigatedElements) { if (expected == actual) { return; } assertIterablesNotNull(expected, actual, indexes, messageOrSupplier); Iterator expectedIterator = expected.iterator(); Iterator actualIterator = actual.iterator(); int processed = 0; while (expectedIterator.hasNext() && actualIterator.hasNext()) { Object expectedElement = expectedIterator.next(); Object actualElement = actualIterator.next(); indexes.addLast(processed); assertIterableElementsEqual(expectedElement, actualElement, indexes, messageOrSupplier, investigatedElements); indexes.removeLast(); processed++; } assertIteratorsAreEmpty(expectedIterator, actualIterator, processed, indexes, messageOrSupplier); } private static void assertIterableElementsEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier, Map investigatedElements) { // If both are equal, we don't need to check recursively. if (Objects.equals(expected, actual)) { return; } // If both are iterables, we need to check whether they contain the same elements. if (expected instanceof Iterable && actual instanceof Iterable) { Pair pair = new Pair(expected, actual); // Before comparing their elements, we check whether we have already checked this pair. Status status = investigatedElements.get(pair); // If we've already determined that both contain the same elements, we don't need to check them again. if (status == Status.CONTAIN_SAME_ELEMENTS) { return; } // If the pair is already under investigation, we fail in order to avoid infinite recursion. if (status == Status.UNDER_INVESTIGATION) { indexes.removeLast(); failIterablesNotEqual(expected, actual, indexes, messageOrSupplier); } // Otherwise, we put the pair under investigation and recurse. investigatedElements.put(pair, Status.UNDER_INVESTIGATION); assertIterableEquals((Iterable) expected, (Iterable) actual, indexes, messageOrSupplier, investigatedElements); // If we reach this point, we've checked that the two iterables contain the same elements so we store this information // in case we come across the same pair again. investigatedElements.put(pair, Status.CONTAIN_SAME_ELEMENTS); } // Otherwise, they are neither equal nor iterables, so we fail. else { assertIterablesNotNull(expected, actual, indexes, messageOrSupplier); failIterablesNotEqual(expected, actual, indexes, messageOrSupplier); } } private static void assertIterablesNotNull(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { if (expected == null) { failExpectedIterableIsNull(indexes, messageOrSupplier); } if (actual == null) { failActualIterableIsNull(indexes, messageOrSupplier); } } private static void failExpectedIterableIsNull(Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected iterable was " + formatIndexes(indexes)) // .buildAndThrow(); } private static void failActualIterableIsNull(Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("actual iterable was " + formatIndexes(indexes)) // .buildAndThrow(); } private static void assertIteratorsAreEmpty(Iterator expected, Iterator actual, int processed, Deque indexes, Object messageOrSupplier) { if (expected.hasNext() || actual.hasNext()) { AtomicInteger expectedCount = new AtomicInteger(processed); expected.forEachRemaining(e -> expectedCount.incrementAndGet()); AtomicInteger actualCount = new AtomicInteger(processed); actual.forEachRemaining(e -> actualCount.incrementAndGet()); assertionFailure() // .message(messageOrSupplier) // .reason("iterable lengths differ" + formatIndexes(indexes)) // .expected(expectedCount.get()) // .actual(actualCount.get()) // .buildAndThrow(); } } private static void failIterablesNotEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("iterable contents differ" + formatIndexes(indexes)) // .expected(expected) // .actual(actual) // .buildAndThrow(); } private final static class Pair { private final Object left; private final Object right; public Pair(Object left, Object right) { this.left = left; this.right = right; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pair that = (Pair) o; return Objects.equals(this.left, that.left) // && Objects.equals(this.right, that.right); } @Override public int hashCode() { return Objects.hash(left, right); } } private enum Status { UNDER_INVESTIGATION, CONTAIN_SAME_ELEMENTS } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java000066400000000000000000000174751455764576500315100ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.lang.String.format; import static java.lang.String.join; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.Preconditions.condition; import static org.junit.platform.commons.util.Preconditions.notNull; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; /** * {@code AssertLinesMatch} is a collection of utility methods that support asserting * lines of {@link String} equality or {@link java.util.regex.Pattern}-match in tests. * * @since 5.0 */ class AssertLinesMatch { private AssertLinesMatch() { /* no-op */ } private static final int MAX_SNIPPET_LENGTH = 21; static void assertLinesMatch(List expectedLines, List actualLines) { assertLinesMatch(expectedLines, actualLines, (Object) null); } static void assertLinesMatch(List expectedLines, List actualLines, String message) { assertLinesMatch(expectedLines, actualLines, (Object) message); } static void assertLinesMatch(Stream expectedLines, Stream actualLines) { assertLinesMatch(expectedLines, actualLines, (Object) null); } static void assertLinesMatch(Stream expectedLines, Stream actualLines, String message) { assertLinesMatch(expectedLines, actualLines, (Object) message); } static void assertLinesMatch(Stream expectedLines, Stream actualLines, Object messageOrSupplier) { notNull(expectedLines, "expectedLines must not be null"); notNull(actualLines, "actualLines must not be null"); // trivial case: same stream instance if (expectedLines == actualLines) { return; } List expectedListOfStrings = expectedLines.collect(Collectors.toList()); List actualListOfStrings = actualLines.collect(Collectors.toList()); assertLinesMatch(expectedListOfStrings, actualListOfStrings, messageOrSupplier); } static void assertLinesMatch(List expectedLines, List actualLines, Object messageOrSupplier) { notNull(expectedLines, "expectedLines must not be null"); notNull(actualLines, "actualLines must not be null"); // trivial case: same list instance if (expectedLines == actualLines) { return; } new LinesMatcher(expectedLines, actualLines, messageOrSupplier).assertLinesMatch(); } private static class LinesMatcher { private final List expectedLines; private final List actualLines; private final Object messageOrSupplier; LinesMatcher(List expectedLines, List actualLines, Object messageOrSupplier) { this.expectedLines = expectedLines; this.actualLines = actualLines; this.messageOrSupplier = messageOrSupplier; } void assertLinesMatch() { int expectedSize = expectedLines.size(); int actualSize = actualLines.size(); // trivial case: when expecting more than actual lines available, something is wrong if (expectedSize > actualSize) { fail("expected %d lines, but only got %d", expectedSize, actualSize); } // simple case: both list are equally sized, compare them line-by-line if (expectedSize == actualSize) { if (IntStream.range(0, expectedSize).allMatch(i -> matches(expectedLines.get(i), actualLines.get(i)))) { return; } // else fall-through to "with fast-forward" matching } assertLinesMatchWithFastForward(); } void assertLinesMatchWithFastForward() { Deque expectedDeque = new ArrayDeque<>(expectedLines); Deque actualDeque = new ArrayDeque<>(actualLines); main: while (!expectedDeque.isEmpty()) { String expectedLine = expectedDeque.pop(); int expectedLineNumber = expectedLines.size() - expectedDeque.size(); // 1-based line number // trivial case: no more actual lines available if (actualDeque.isEmpty()) { fail("expected line #%d:`%s` not found - actual lines depleted", expectedLineNumber, snippet(expectedLine)); } String actualLine = actualDeque.peek(); // trivial case: take the fast path when they match if (matches(expectedLine, actualLine)) { actualDeque.pop(); continue; // main } // fast-forward marker found in expected line: fast-forward actual line... if (isFastForwardLine(expectedLine)) { int fastForwardLimit = parseFastForwardLimit(expectedLine); int actualRemaining = actualDeque.size(); // trivial case: fast-forward marker was in last expected line if (expectedDeque.isEmpty()) { // no limit given or perfect match? we're done. if (fastForwardLimit == Integer.MAX_VALUE || fastForwardLimit == actualRemaining) { return; } fail("terminal fast-forward(%d) error: fast-forward(%d) expected", fastForwardLimit, actualRemaining); } // fast-forward limit was given: use it if (fastForwardLimit != Integer.MAX_VALUE) { if (actualRemaining < fastForwardLimit) { fail("fast-forward(%d) error: not enough actual lines remaining (%s)", fastForwardLimit, actualRemaining); } // fast-forward now: actualDeque.pop(fastForwardLimit) for (int i = 0; i < fastForwardLimit; i++) { actualDeque.pop(); } continue; // main } // peek next expected line expectedLine = expectedDeque.peek(); // fast-forward "unlimited": until next match while (true) { if (actualDeque.isEmpty()) { fail("fast-forward(∞) didn't find: `%s`", snippet(expectedLine)); } if (matches(expectedLine, actualDeque.peek())) { continue main; } actualDeque.pop(); } } int actualLineNumber = actualLines.size() - actualDeque.size() + 1; // 1-based line number fail("expected line #%d doesn't match actual line #%d%n" + "\texpected: `%s`%n" + "\t actual: `%s`", expectedLineNumber, actualLineNumber, expectedLine, actualLine); } // after math if (!actualDeque.isEmpty()) { fail("more actual lines than expected: %d", actualDeque.size()); } } String snippet(String line) { if (line.length() <= MAX_SNIPPET_LENGTH) { return line; } return line.substring(0, MAX_SNIPPET_LENGTH - 5) + "[...]"; } void fail(String format, Object... args) { String newLine = System.lineSeparator(); assertionFailure() // .message(messageOrSupplier) // .reason(format(format, args)) // .expected(join(newLine, expectedLines)) // .actual(join(newLine, actualLines)) // .includeValuesInMessage(false) // .buildAndThrow(); } } static boolean isFastForwardLine(String line) { line = line.trim(); return line.length() >= 4 && line.startsWith(">>") && line.endsWith(">>"); } static int parseFastForwardLimit(String fastForwardLine) { fastForwardLine = fastForwardLine.trim(); String text = fastForwardLine.substring(2, fastForwardLine.length() - 2).trim(); try { int limit = Integer.parseInt(text); condition(limit > 0, () -> format("fast-forward(%d) limit must be greater than zero", limit)); return limit; } catch (NumberFormatException e) { return Integer.MAX_VALUE; } } static boolean matches(String expectedLine, String actualLine) { notNull(expectedLine, "expected line must not be null"); notNull(actualLine, "actual line must not be null"); if (expectedLine.equals(actualLine)) { return true; } try { return actualLine.matches(expectedLine); } catch (PatternSyntaxException ignore) { return false; } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java000066400000000000000000000145331455764576500313640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.doublesAreEqual; import static org.junit.jupiter.api.AssertionUtils.floatsAreEqual; import static org.junit.jupiter.api.AssertionUtils.objectsAreEqual; import java.util.function.Supplier; /** * {@code AssertNotEquals} is a collection of utility methods that support asserting * inequality in objects and primitive values in tests. * * @since 5.0 */ class AssertNotEquals { private AssertNotEquals() { /* no-op */ } /** * @since 5.4 */ static void assertNotEquals(byte unexpected, byte actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(byte unexpected, byte actual, String message) { if (unexpected == actual) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(short unexpected, short actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(short unexpected, short actual, String message) { if (unexpected == actual) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(int unexpected, int actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(int unexpected, int actual, String message) { if (unexpected == actual) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(int unexpected, int actual, Supplier messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(long unexpected, long actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(long unexpected, long actual, String message) { if (unexpected == actual) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual, String message) { if (floatsAreEqual(unexpected, actual)) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { if (floatsAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual, float delta) { assertNotEquals(unexpected, actual, delta, (String) null); } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual, float delta, String message) { if (floatsAreEqual(unexpected, actual, delta)) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(float unexpected, float actual, float delta, Supplier messageSupplier) { if (floatsAreEqual(unexpected, actual, delta)) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual, String message) { if (doublesAreEqual(unexpected, actual)) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { if (doublesAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual, double delta) { assertNotEquals(unexpected, actual, delta, (String) null); } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual, double delta, String message) { if (doublesAreEqual(unexpected, actual, delta)) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(double unexpected, double actual, double delta, Supplier messageSupplier) { if (doublesAreEqual(unexpected, actual, delta)) { failEqual(actual, messageSupplier); } } /** * @since 5.4 */ static void assertNotEquals(char unexpected, char actual) { assertNotEquals(unexpected, actual, (String) null); } /** * @since 5.4 */ static void assertNotEquals(char unexpected, char actual, String message) { if (unexpected == actual) { failEqual(actual, message); } } /** * @since 5.4 */ static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } static void assertNotEquals(Object unexpected, Object actual) { assertNotEquals(unexpected, actual, (String) null); } static void assertNotEquals(Object unexpected, Object actual, String message) { if (objectsAreEqual(unexpected, actual)) { failEqual(actual, message); } } static void assertNotEquals(Object unexpected, Object actual, Supplier messageSupplier) { if (objectsAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } } private static void failEqual(Object actual, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not equal but was: <" + actual + ">") // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java000066400000000000000000000022501455764576500310350ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; /** * {@code AssertNotNull} is a collection of utility methods that support asserting * that there is an object. * * @since 5.0 */ class AssertNotNull { private AssertNotNull() { /* no-op */ } static void assertNotNull(Object actual) { assertNotNull(actual, (String) null); } static void assertNotNull(Object actual, String message) { if (actual == null) { failNull(message); } } static void assertNotNull(Object actual, Supplier messageSupplier) { if (actual == null) { failNull(messageSupplier); } } private static void failNull(Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not ") // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java000066400000000000000000000024661455764576500310210ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; /** * {@code AssertNotSame} is a collection of utility methods that support asserting * two objects are not the same. * * @since 5.0 */ class AssertNotSame { private AssertNotSame() { /* no-op */ } static void assertNotSame(Object unexpected, Object actual) { assertNotSame(unexpected, actual, (String) null); } static void assertNotSame(Object unexpected, Object actual, String message) { if (unexpected == actual) { failSame(actual, message); } } static void assertNotSame(Object unexpected, Object actual, Supplier messageSupplier) { if (unexpected == actual) { failSame(actual, messageSupplier); } } private static void failSame(Object actual, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not same but was: <" + actual + ">") // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java000066400000000000000000000022761455764576500303640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; /** * {@code AssertNull} is a collection of utility methods that support asserting * there is no object. * * @since 5.0 */ class AssertNull { private AssertNull() { /* no-op */ } static void assertNull(Object actual) { assertNull(actual, (String) null); } static void assertNull(Object actual, String message) { if (actual != null) { failNotNull(actual, message); } } static void assertNull(Object actual, Supplier messageSupplier) { if (actual != null) { failNotNull(actual, messageSupplier); } } private static void failNotNull(Object actual, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(null) // .actual(actual) // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java000066400000000000000000000024621455764576500303340ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; /** * {@code AssertSame} is a collection of utility methods that support asserting * two objects are the same. * * @since 5.0 */ class AssertSame { private AssertSame() { /* no-op */ } static void assertSame(Object expected, Object actual) { assertSame(expected, actual, (String) null); } static void assertSame(Object expected, Object actual, String message) { if (expected != actual) { failNotSame(expected, actual, message); } } static void assertSame(Object expected, Object actual, Supplier messageSupplier) { if (expected != actual) { failNotSame(expected, actual, messageSupplier); } } private static void failNotSame(Object expected, Object actual, Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(expected) // .actual(actual) // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java000066400000000000000000000044111455764576500307310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.lang.String.format; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * {@code AssertThrows} is a collection of utility methods that support asserting * an exception of an expected type is thrown. * * @since 5.0 */ class AssertThrows { private AssertThrows() { /* no-op */ } static T assertThrows(Class expectedType, Executable executable) { return assertThrows(expectedType, executable, (Object) null); } static T assertThrows(Class expectedType, Executable executable, String message) { return assertThrows(expectedType, executable, (Object) message); } static T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier) { return assertThrows(expectedType, executable, (Object) messageSupplier); } @SuppressWarnings("unchecked") private static T assertThrows(Class expectedType, Executable executable, Object messageOrSupplier) { try { executable.execute(); } catch (Throwable actualException) { if (expectedType.isInstance(actualException)) { return (T) actualException; } else { UnrecoverableExceptions.rethrowIfUnrecoverable(actualException); throw assertionFailure() // .message(messageOrSupplier) // .expected(expectedType) // .actual(actualException.getClass()) // .reason("Unexpected exception type thrown") // .cause(actualException) // .build(); } } throw assertionFailure() // .message(messageOrSupplier) // .reason(format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType))) // .build(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java000066400000000000000000000045241455764576500322700ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.lang.String.format; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * {@code AssertThrowsExactly} is a collection of utility methods that support asserting * an exception of an exact type is thrown. * * @since 5.8 */ class AssertThrowsExactly { private AssertThrowsExactly() { /* no-op */ } static T assertThrowsExactly(Class expectedType, Executable executable) { return assertThrowsExactly(expectedType, executable, (Object) null); } static T assertThrowsExactly(Class expectedType, Executable executable, String message) { return assertThrowsExactly(expectedType, executable, (Object) message); } static T assertThrowsExactly(Class expectedType, Executable executable, Supplier messageSupplier) { return assertThrowsExactly(expectedType, executable, (Object) messageSupplier); } @SuppressWarnings("unchecked") private static T assertThrowsExactly(Class expectedType, Executable executable, Object messageOrSupplier) { try { executable.execute(); } catch (Throwable actualException) { if (expectedType.equals(actualException.getClass())) { return (T) actualException; } else { UnrecoverableExceptions.rethrowIfUnrecoverable(actualException); throw assertionFailure() // .message(messageOrSupplier) // .expected(expectedType) // .actual(actualException.getClass()) // .reason("Unexpected exception type thrown") // .cause(actualException) // .build(); } } throw assertionFailure() // .message(messageOrSupplier) // .reason(format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType))) // .build(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java000066400000000000000000000050521455764576500310730ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; import java.time.Duration; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; /** * {@code AssertTimeout} is a collection of utility methods that support asserting * the execution of the code under test did not take longer than the timeout duration. * * @since 5.0 */ class AssertTimeout { private AssertTimeout() { /* no-op */ } static void assertTimeout(Duration timeout, Executable executable) { assertTimeout(timeout, executable, (String) null); } static void assertTimeout(Duration timeout, Executable executable, String message) { assertTimeout(timeout, () -> { executable.execute(); return null; }, message); } static void assertTimeout(Duration timeout, Executable executable, Supplier messageSupplier) { assertTimeout(timeout, () -> { executable.execute(); return null; }, messageSupplier); } static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { return assertTimeout(timeout, supplier, (Object) null); } static T assertTimeout(Duration timeout, ThrowingSupplier supplier, String message) { return assertTimeout(timeout, supplier, (Object) message); } static T assertTimeout(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier) { return assertTimeout(timeout, supplier, (Object) messageSupplier); } private static T assertTimeout(Duration timeout, ThrowingSupplier supplier, Object messageOrSupplier) { long timeoutInMillis = timeout.toMillis(); long start = System.currentTimeMillis(); T result = null; try { result = supplier.get(); } catch (Throwable ex) { throwAsUncheckedException(ex); } long timeElapsed = System.currentTimeMillis() - start; if (timeElapsed > timeoutInMillis) { assertionFailure() // .message(messageOrSupplier) // .reason("execution exceeded timeout of " + timeoutInMillis + " ms by " + (timeElapsed - timeoutInMillis) + " ms") // .buildAndThrow(); } return result; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeoutPreemptively.java000066400000000000000000000126751455764576500335120ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; import java.time.Duration; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.JUnitException; import org.opentest4j.AssertionFailedError; /** * {@code AssertTimeout} is a collection of utility methods that support asserting * the execution of the code under test did not take longer than the timeout duration * using a preemptive approach. * * @since 5.9.1 */ class AssertTimeoutPreemptively { static void assertTimeoutPreemptively(Duration timeout, Executable executable) { assertTimeoutPreemptively(timeout, executable, (String) null); } static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message) { assertTimeoutPreemptively(timeout, () -> { executable.execute(); return null; }, message); } static void assertTimeoutPreemptively(Duration timeout, Executable executable, Supplier messageSupplier) { assertTimeoutPreemptively(timeout, () -> { executable.execute(); return null; }, messageSupplier); } static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier) { return assertTimeoutPreemptively(timeout, supplier, null, AssertTimeoutPreemptively::createAssertionFailure); } static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, String message) { return assertTimeoutPreemptively(timeout, supplier, message == null ? null : () -> message, AssertTimeoutPreemptively::createAssertionFailure); } static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier) { return assertTimeoutPreemptively(timeout, supplier, messageSupplier, AssertTimeoutPreemptively::createAssertionFailure); } static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier, Assertions.TimeoutFailureFactory failureFactory) throws E { AtomicReference threadReference = new AtomicReference<>(); ExecutorService executorService = Executors.newSingleThreadExecutor(new TimeoutThreadFactory()); try { Future future = submitTask(supplier, threadReference, executorService); return resolveFutureAndHandleException(future, timeout, messageSupplier, threadReference::get, failureFactory); } finally { executorService.shutdownNow(); } } private static Future submitTask(ThrowingSupplier supplier, AtomicReference threadReference, ExecutorService executorService) { return executorService.submit(() -> { try { threadReference.set(Thread.currentThread()); return supplier.get(); } catch (Throwable throwable) { throw throwAsUncheckedException(throwable); } }); } private static T resolveFutureAndHandleException(Future future, Duration timeout, Supplier messageSupplier, Supplier threadSupplier, Assertions.TimeoutFailureFactory failureFactory) throws E { try { return future.get(timeout.toMillis(), TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { Thread thread = threadSupplier.get(); ExecutionTimeoutException cause = null; if (thread != null) { cause = new ExecutionTimeoutException("Execution timed out in thread " + thread.getName()); cause.setStackTrace(thread.getStackTrace()); } throw failureFactory.createTimeoutFailure(timeout, messageSupplier, cause); } catch (ExecutionException ex) { throw throwAsUncheckedException(ex.getCause()); } catch (Throwable ex) { throw throwAsUncheckedException(ex); } } private static AssertionFailedError createAssertionFailure(Duration timeout, Supplier messageSupplier, Throwable cause) { return assertionFailure() // .message(messageSupplier) // .reason("execution timed out after " + timeout.toMillis() + " ms") // .cause(cause) // .build(); } private static class ExecutionTimeoutException extends JUnitException { private static final long serialVersionUID = 1L; ExecutionTimeoutException(String message) { super(message); } } /** * The thread factory used for preemptive timeout. *

* The factory creates threads with meaningful names, helpful for debugging purposes. */ private static class TimeoutThreadFactory implements ThreadFactory { private static final AtomicInteger threadNumber = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "junit-timeout-thread-" + threadNumber.getAndIncrement()); } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java000066400000000000000000000031651455764576500303670ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.BooleanSupplier; import java.util.function.Supplier; /** * {@code AssertTrue} is a collection of utility methods that support asserting * {@code true} in tests. * * @since 5.0 */ class AssertTrue { private AssertTrue() { /* no-op */ } static void assertTrue(boolean condition) { assertTrue(condition, (String) null); } static void assertTrue(boolean condition, String message) { if (!condition) { failNotTrue(message); } } static void assertTrue(boolean condition, Supplier messageSupplier) { if (!condition) { failNotTrue(messageSupplier); } } static void assertTrue(BooleanSupplier booleanSupplier) { assertTrue(booleanSupplier.getAsBoolean(), (String) null); } static void assertTrue(BooleanSupplier booleanSupplier, String message) { assertTrue(booleanSupplier.getAsBoolean(), message); } static void assertTrue(BooleanSupplier booleanSupplier, Supplier messageSupplier) { assertTrue(booleanSupplier.getAsBoolean(), messageSupplier); } private static void failNotTrue(Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(true) // .actual(false) // .buildAndThrow(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java000066400000000000000000000137231455764576500330550ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.util.StringUtils; import org.opentest4j.AssertionFailedError; /** * Builder for {@link AssertionFailedError AssertionFailedErrors}. *

* Using this builder ensures consistency in how failure message are formatted * within JUnit Jupiter and for custom user-defined assertions. * * @since 5.9 * @see AssertionFailedError */ @API(status = STABLE, since = "5.9") public class AssertionFailureBuilder { private Object message; private Throwable cause; private boolean mismatch; private Object expected; private Object actual; private String reason; private boolean includeValuesInMessage = true; /** * Create a new {@code AssertionFailureBuilder}. */ public static AssertionFailureBuilder assertionFailure() { return new AssertionFailureBuilder(); } private AssertionFailureBuilder() { } /** * Set the user-defined message of the assertion. *

* The {@code message} may be passed as a {@link Supplier} or plain * {@link String}. If any other type is passed, it is converted to * {@code String} as per {@link StringUtils#nullSafeToString(Object)}. * * @param message the user-defined failure message; may be {@code null} * @return this builder for method chaining */ public AssertionFailureBuilder message(Object message) { this.message = message; return this; } /** * Set the reason why the assertion failed. * * @param reason the failure reason; may be {@code null} * @return this builder for method chaining */ public AssertionFailureBuilder reason(String reason) { this.reason = reason; return this; } /** * Set the cause of the assertion failure. * * @param cause the failure cause; may be {@code null} * @return this builder for method chaining */ public AssertionFailureBuilder cause(Throwable cause) { this.cause = cause; return this; } /** * Set the expected value of the assertion. * * @param expected the expected value; may be {@code null} * @return this builder for method chaining */ public AssertionFailureBuilder expected(Object expected) { this.mismatch = true; this.expected = expected; return this; } /** * Set the actual value of the assertion. * * @param actual the actual value; may be {@code null} * @return this builder for method chaining */ public AssertionFailureBuilder actual(Object actual) { this.mismatch = true; this.actual = actual; return this; } /** * Set whether to include the actual and expected values in the generated * failure message. * * @param includeValuesInMessage whether to include the actual and expected * values * @return this builder for method chaining */ public AssertionFailureBuilder includeValuesInMessage(boolean includeValuesInMessage) { this.includeValuesInMessage = includeValuesInMessage; return this; } /** * Build the {@link AssertionFailedError AssertionFailedError} and throw it. * * @throws AssertionFailedError always */ public void buildAndThrow() throws AssertionFailedError { throw build(); } /** * Build the {@link AssertionFailedError AssertionFailedError} without * throwing it. * * @return the built assertion failure */ public AssertionFailedError build() { String reason = nullSafeGet(this.reason); if (mismatch && includeValuesInMessage) { reason = (reason == null ? "" : reason + ", ") + formatValues(expected, actual); } String message = nullSafeGet(this.message); if (reason != null) { message = buildPrefix(message) + reason; } return mismatch // ? new AssertionFailedError(message, expected, actual, cause) // : new AssertionFailedError(message, cause); } private static String nullSafeGet(Object messageOrSupplier) { if (messageOrSupplier == null) { return null; } if (messageOrSupplier instanceof Supplier) { Object message = ((Supplier) messageOrSupplier).get(); return StringUtils.nullSafeToString(message); } return StringUtils.nullSafeToString(messageOrSupplier); } private static String buildPrefix(String message) { return (StringUtils.isNotBlank(message) ? message + " ==> " : ""); } private static String formatValues(Object expected, Object actual) { String expectedString = toString(expected); String actualString = toString(actual); if (expectedString.equals(actualString)) { return String.format("expected: %s but was: %s", formatClassAndValue(expected, expectedString), formatClassAndValue(actual, actualString)); } return String.format("expected: <%s> but was: <%s>", expectedString, actualString); } private static String formatClassAndValue(Object value, String valueString) { // If the value is null, return instead of null. if (value == null) { return ""; } String classAndHash = getClassName(value) + toHash(value); // if it's a class, there's no need to repeat the class name contained in the valueString. return (value instanceof Class ? "<" + classAndHash + ">" : classAndHash + "<" + valueString + ">"); } private static String toString(Object obj) { if (obj instanceof Class) { return getCanonicalName((Class) obj); } return StringUtils.nullSafeToString(obj); } private static String toHash(Object obj) { return (obj == null ? "" : "@" + Integer.toHexString(System.identityHashCode(obj))); } private static String getClassName(Object obj) { return (obj == null ? "null" : obj instanceof Class ? getCanonicalName((Class) obj) : obj.getClass().getName()); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java000066400000000000000000000060721455764576500312560ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.stream.Collectors.joining; import java.util.Deque; import java.util.function.Supplier; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.AssertionFailedError; /** * {@code AssertionUtils} is a collection of utility methods that are common to * all assertion implementations. * * @since 5.0 */ class AssertionUtils { private AssertionUtils() { /* no-op */ } static void fail() { throw new AssertionFailedError(); } static void fail(String message) { throw new AssertionFailedError(message); } static void fail(String message, Throwable cause) { throw new AssertionFailedError(message, cause); } static void fail(Throwable cause) { throw new AssertionFailedError(null, cause); } static void fail(Supplier messageSupplier) { throw new AssertionFailedError(nullSafeGet(messageSupplier)); } static String nullSafeGet(Supplier messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } static String getCanonicalName(Class clazz) { try { String canonicalName = clazz.getCanonicalName(); return (canonicalName != null ? canonicalName : clazz.getName()); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); return clazz.getName(); } } static String formatIndexes(Deque indexes) { if (indexes == null || indexes.isEmpty()) { return ""; } String indexesString = indexes.stream().map(Object::toString).collect(joining("][", "[", "]")); return " at index " + indexesString; } static boolean floatsAreEqual(float value1, float value2, float delta) { assertValidDelta(delta); return floatsAreEqual(value1, value2) || Math.abs(value1 - value2) <= delta; } static void assertValidDelta(float delta) { if (Float.isNaN(delta) || delta < 0.0) { failIllegalDelta(String.valueOf(delta)); } } static void assertValidDelta(double delta) { if (Double.isNaN(delta) || delta < 0.0) { failIllegalDelta(String.valueOf(delta)); } } static boolean floatsAreEqual(float value1, float value2) { return Float.floatToIntBits(value1) == Float.floatToIntBits(value2); } static boolean doublesAreEqual(double value1, double value2, double delta) { assertValidDelta(delta); return doublesAreEqual(value1, value2) || Math.abs(value1 - value2) <= delta; } static boolean doublesAreEqual(double value1, double value2) { return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2); } static boolean objectsAreEqual(Object obj1, Object obj2) { if (obj1 == null) { return (obj2 == null); } return obj1.equals(obj2); } private static void failIllegalDelta(String delta) { fail("positive delta expected but was: <" + delta + ">"); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assertions.java000066400000000000000000004142511455764576500304220ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import java.time.Duration; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.opentest4j.MultipleFailuresError; /** * {@code Assertions} is a collection of utility methods that support asserting * conditions in tests. * *

Unless otherwise noted, a failed assertion will throw an * {@link org.opentest4j.AssertionFailedError} or a subclass thereof. * *

Object Equality

* *

Assertion methods comparing two objects for equality, such as the * {@code assertEquals(expected, actual)} and {@code assertNotEquals(unexpected, actual)} * variants, are only intended to test equality for an (un-)expected value * and an actual value. They are not designed for testing whether a class correctly * implements {@link Object#equals(Object)}. For example, {@code assertEquals()} * might immediately return {@code true} when provided the same object for the * expected and actual values, without calling {@code equals(Object)} at all. * Tests that aim to verify the {@code equals(Object)} implementation should instead * be written to explicitly verify the {@link Object#equals(Object)} contract by * using {@link #assertTrue(boolean) assertTrue()} or {@link #assertFalse(boolean) * assertFalse()} — for example, {@code assertTrue(expected.equals(actual))}, * {@code assertTrue(actual.equals(expected))}, {@code assertFalse(expected.equals(null))}, * etc. * *

Kotlin Support

* *

Additional Kotlin assertions can be * found as top-level functions in the {@link org.junit.jupiter.api} * package. * *

Preemptive Timeouts

* *

The various {@code assertTimeoutPreemptively()} methods in this class * execute the provided callback ({@code executable} or {@code supplier}) in a * different thread than that of the calling code. If the timeout is exceeded, * an attempt will be made to preemptively abort execution of the callback by * {@linkplain Thread#interrupt() interrupting} the callback's thread. If the * callback's thread does not return when interrupted, the thread will continue * to run in the background after the {@code assertTimeoutPreemptively()} method * has returned. * *

Furthermore, the behavior of {@code assertTimeoutPreemptively()} methods * can lead to undesirable side effects if the code that is executed within the * callback relies on {@link ThreadLocal} storage. One common example of this is * the transactional testing support in the Spring Framework. Specifically, Spring's * testing support binds transaction state to the current thread (via a * {@code ThreadLocal}) before a test method is invoked. Consequently, if a * callback provided to {@code assertTimeoutPreemptively()} invokes Spring-managed * components that participate in transactions, any actions taken by those * components will not be rolled back with the test-managed transaction. On the * contrary, such actions will be committed to the persistent store (e.g., * relational database) even though the test-managed transaction is rolled back. * Similar side effects may be encountered with other frameworks that rely on * {@code ThreadLocal} storage. * *

Extensibility

* *

Although it is technically possible to extend this class, extension is * strongly discouraged. The JUnit Team highly recommends that the methods * defined in this class be used via static imports. * * @since 5.0 * @see org.opentest4j.AssertionFailedError * @see Assumptions */ @API(status = STABLE, since = "5.0") public class Assertions { /** * Protected constructor allowing subclassing but not direct instantiation. * * @since 5.3 */ @API(status = STABLE, since = "5.3") protected Assertions() { /* no-op */ } // --- fail ---------------------------------------------------------------- /** * Fail the test without a failure message. * *

Although failing with an explicit failure message is recommended, * this method may be useful when maintaining legacy code. * *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ public static V fail() { AssertionUtils.fail(); return null; // appeasing the compiler: this line will never be executed. } /** * Fail the test with the given failure {@code message}. * *

The generic return type {@code V} allows this method to be used * directly as a single-statement lambda expression, thereby avoiding the * need to implement a code block with an explicit return value. Since this * method throws an {@link org.opentest4j.AssertionFailedError} before its * return statement, this method never actually returns a value to its caller. * The following example demonstrates how this may be used in practice. * *

{@code
	 * Stream.of().map(entry -> fail("should not be called"));
	 * }
*/ public static V fail(String message) { AssertionUtils.fail(message); return null; // appeasing the compiler: this line will never be executed. } /** * Fail the test with the given failure {@code message} as well * as the underlying {@code cause}. * *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ public static V fail(String message, Throwable cause) { AssertionUtils.fail(message, cause); return null; // appeasing the compiler: this line will never be executed. } /** * Fail the test with the given underlying {@code cause}. * *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ public static V fail(Throwable cause) { AssertionUtils.fail(cause); return null; // appeasing the compiler: this line will never be executed. } /** * Fail the test with the failure message retrieved from the * given {@code messageSupplier}. * *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ public static V fail(Supplier messageSupplier) { AssertionUtils.fail(messageSupplier); return null; // appeasing the compiler: this line will never be executed. } // --- assertTrue ---------------------------------------------------------- /** * Assert that the supplied {@code condition} is {@code true}. */ public static void assertTrue(boolean condition) { AssertTrue.assertTrue(condition); } /** * Assert that the supplied {@code condition} is {@code true}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertTrue(boolean condition, Supplier messageSupplier) { AssertTrue.assertTrue(condition, messageSupplier); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code true}. */ public static void assertTrue(BooleanSupplier booleanSupplier) { AssertTrue.assertTrue(booleanSupplier); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code true}. *

Fails with the supplied failure {@code message}. */ public static void assertTrue(BooleanSupplier booleanSupplier, String message) { AssertTrue.assertTrue(booleanSupplier, message); } /** * Assert that the supplied {@code condition} is {@code true}. *

Fails with the supplied failure {@code message}. */ public static void assertTrue(boolean condition, String message) { AssertTrue.assertTrue(condition, message); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code true}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertTrue(BooleanSupplier booleanSupplier, Supplier messageSupplier) { AssertTrue.assertTrue(booleanSupplier, messageSupplier); } // --- assertFalse --------------------------------------------------------- /** * Assert that the supplied {@code condition} is {@code false}. */ public static void assertFalse(boolean condition) { AssertFalse.assertFalse(condition); } /** * Assert that the supplied {@code condition} is {@code false}. *

Fails with the supplied failure {@code message}. */ public static void assertFalse(boolean condition, String message) { AssertFalse.assertFalse(condition, message); } /** * Assert that the supplied {@code condition} is {@code false}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertFalse(boolean condition, Supplier messageSupplier) { AssertFalse.assertFalse(condition, messageSupplier); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code false}. */ public static void assertFalse(BooleanSupplier booleanSupplier) { AssertFalse.assertFalse(booleanSupplier); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code false}. *

Fails with the supplied failure {@code message}. */ public static void assertFalse(BooleanSupplier booleanSupplier, String message) { AssertFalse.assertFalse(booleanSupplier, message); } /** * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code false}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertFalse(BooleanSupplier booleanSupplier, Supplier messageSupplier) { AssertFalse.assertFalse(booleanSupplier, messageSupplier); } // --- assertNull ---------------------------------------------------------- /** * Assert that {@code actual} is {@code null}. */ public static void assertNull(Object actual) { AssertNull.assertNull(actual); } /** * Assert that {@code actual} is {@code null}. *

Fails with the supplied failure {@code message}. */ public static void assertNull(Object actual, String message) { AssertNull.assertNull(actual, message); } /** * Assert that {@code actual} is {@code null}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertNull(Object actual, Supplier messageSupplier) { AssertNull.assertNull(actual, messageSupplier); } // --- assertNotNull ------------------------------------------------------- /** * Assert that {@code actual} is not {@code null}. */ public static void assertNotNull(Object actual) { AssertNotNull.assertNotNull(actual); } /** * Assert that {@code actual} is not {@code null}. *

Fails with the supplied failure {@code message}. */ public static void assertNotNull(Object actual, String message) { AssertNotNull.assertNotNull(actual, message); } /** * Assert that {@code actual} is not {@code null}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertNotNull(Object actual, Supplier messageSupplier) { AssertNotNull.assertNotNull(actual, messageSupplier); } // --- assertEquals -------------------------------------------------------- /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(short expected, short actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(short expected, Short actual) { AssertEquals.assertEquals((Short) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(Short expected, short actual) { AssertEquals.assertEquals(expected, (Short) actual); } /** * Assert that {@code expected} and {@code actual} are equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Short expected, Short actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(short expected, short actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(short expected, Short actual, String message) { AssertEquals.assertEquals((Short) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Short expected, short actual, String message) { AssertEquals.assertEquals(expected, (Short) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Short expected, Short actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(short expected, short actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(short expected, Short actual, Supplier messageSupplier) { AssertEquals.assertEquals((Short) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Short expected, short actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Short) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Short expected, Short actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(byte expected, byte actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(byte expected, Byte actual) { AssertEquals.assertEquals((Byte) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(Byte expected, byte actual) { AssertEquals.assertEquals(expected, (Byte) actual); } /** * Assert that {@code expected} and {@code actual} are equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Byte expected, Byte actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(byte expected, byte actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(byte expected, Byte actual, String message) { AssertEquals.assertEquals((Byte) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Byte expected, byte actual, String message) { AssertEquals.assertEquals(expected, (Byte) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Byte expected, Byte actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(byte expected, byte actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(byte expected, Byte actual, Supplier messageSupplier) { AssertEquals.assertEquals((Byte) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Byte expected, byte actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Byte) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Byte expected, Byte actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(int expected, int actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(int expected, Integer actual) { AssertEquals.assertEquals((Integer) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(Integer expected, int actual) { AssertEquals.assertEquals(expected, (Integer) actual); } /** * Assert that {@code expected} and {@code actual} are equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Integer expected, Integer actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(int expected, int actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(int expected, Integer actual, String message) { AssertEquals.assertEquals((Integer) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Integer expected, int actual, String message) { AssertEquals.assertEquals(expected, (Integer) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Integer expected, Integer actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(int expected, int actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(int expected, Integer actual, Supplier messageSupplier) { AssertEquals.assertEquals((Integer) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Integer expected, int actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Integer) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Integer expected, Integer actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(long expected, long actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(long expected, Long actual) { AssertEquals.assertEquals((Long) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(Long expected, long actual) { AssertEquals.assertEquals(expected, (Long) actual); } /** * Assert that {@code expected} and {@code actual} are equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Long expected, Long actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(long expected, long actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(long expected, Long actual, String message) { AssertEquals.assertEquals((Long) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Long expected, long actual, String message) { AssertEquals.assertEquals(expected, (Long) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Long expected, Long actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(long expected, long actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(long expected, Long actual, Supplier messageSupplier) { AssertEquals.assertEquals((Long) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Long expected, long actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Long) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Long expected, Long actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertEquals(float expected, float actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertEquals(float expected, Float actual) { AssertEquals.assertEquals((Float) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertEquals(Float expected, float actual) { AssertEquals.assertEquals(expected, (Float) actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Float expected, Float actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(float expected, float actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(float expected, Float actual, String message) { AssertEquals.assertEquals((Float) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Float expected, float actual, String message) { AssertEquals.assertEquals(expected, (Float) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Float expected, Float actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(float expected, float actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(float expected, Float actual, Supplier messageSupplier) { AssertEquals.assertEquals((Float) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Float expected, float actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Float) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Float expected, Float actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertEquals(float expected, float actual, float delta) { AssertEquals.assertEquals(expected, actual, delta); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(float expected, float actual, float delta, String message) { AssertEquals.assertEquals(expected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(float expected, float actual, float delta, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertEquals(double expected, double actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertEquals(double expected, Double actual) { AssertEquals.assertEquals((Double) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertEquals(Double expected, double actual) { AssertEquals.assertEquals(expected, (Double) actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Double expected, Double actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(double expected, double actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(double expected, Double actual, String message) { AssertEquals.assertEquals((Double) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Double expected, double actual, String message) { AssertEquals.assertEquals(expected, (Double) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Double expected, Double actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(double expected, double actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(double expected, Double actual, Supplier messageSupplier) { AssertEquals.assertEquals((Double) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Double expected, double actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Double) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Double expected, Double actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertEquals(double expected, double actual, double delta) { AssertEquals.assertEquals(expected, actual, delta); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(double expected, double actual, double delta, String message) { AssertEquals.assertEquals(expected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(double expected, double actual, double delta, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(char expected, char actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(char expected, Character actual) { AssertEquals.assertEquals((Character) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ public static void assertEquals(Character expected, char actual) { AssertEquals.assertEquals(expected, (Character) actual); } /** * Assert that {@code expected} and {@code actual} are equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Character expected, Character actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(char expected, char actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(char expected, Character actual, String message) { AssertEquals.assertEquals((Character) expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ public static void assertEquals(Character expected, char actual, String message) { AssertEquals.assertEquals(expected, (Character) actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Character expected, Character actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(char expected, char actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(char expected, Character actual, Supplier messageSupplier) { AssertEquals.assertEquals((Character) expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertEquals(Character expected, char actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, (Character) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertEquals(Character expected, Character actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are equal. *

If both are {@code null}, they are considered equal. * * @see Object#equals(Object) */ public static void assertEquals(Object expected, Object actual) { AssertEquals.assertEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. * * @see Object#equals(Object) */ public static void assertEquals(Object expected, Object actual, String message) { AssertEquals.assertEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @see Object#equals(Object) */ public static void assertEquals(Object expected, Object actual, Supplier messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } // --- assertArrayEquals --------------------------------------------------- /** * Assert that {@code expected} and {@code actual} boolean arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(boolean[] expected, boolean[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} boolean arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(boolean[] expected, boolean[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} boolean arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(boolean[] expected, boolean[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} char arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(char[] expected, char[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} char arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(char[] expected, char[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} char arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(char[] expected, char[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} byte arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(byte[] expected, byte[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} byte arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(byte[] expected, byte[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} byte arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(byte[] expected, byte[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} short arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(short[] expected, short[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} short arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(short[] expected, short[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} short arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(short[] expected, short[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} int arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(int[] expected, int[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} int arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(int[] expected, int[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} int arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(int[] expected, int[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} long arrays are equal. *

If both are {@code null}, they are considered equal. */ public static void assertArrayEquals(long[] expected, long[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} long arrays are equal. *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(long[] expected, long[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} long arrays are equal. *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(long[] expected, long[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} float arrays are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertArrayEquals(float[] expected, float[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} float arrays are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(float[] expected, float[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} float arrays are equal. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(float[] expected, float[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} float arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ public static void assertArrayEquals(float[] expected, float[] actual, float delta) { AssertArrayEquals.assertArrayEquals(expected, actual, delta); } /** * Assert that {@code expected} and {@code actual} float arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(float[] expected, float[] actual, float delta, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} float arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(float[] expected, float[] actual, float delta, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} double arrays are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertArrayEquals(double[] expected, double[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} double arrays are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(double[] expected, double[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} double arrays are equal. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(double[] expected, double[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} double arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ public static void assertArrayEquals(double[] expected, double[] actual, double delta) { AssertArrayEquals.assertArrayEquals(expected, actual, delta); } /** * Assert that {@code expected} and {@code actual} double arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ public static void assertArrayEquals(double[] expected, double[] actual, double delta, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} double arrays are equal within the given non-negative {@code delta}. *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ public static void assertArrayEquals(double[] expected, double[] actual, double delta, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} object arrays are deeply equal. *

If both are {@code null}, they are considered equal. *

Nested float arrays are checked as in {@link #assertEquals(float, float)}. *

Nested double arrays are checked as in {@link #assertEquals(double, double)}. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ public static void assertArrayEquals(Object[] expected, Object[] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} object arrays are deeply equal. *

If both are {@code null}, they are considered equal. *

Nested float arrays are checked as in {@link #assertEquals(float, float)}. *

Nested double arrays are checked as in {@link #assertEquals(double, double)}. *

Fails with the supplied failure {@code message}. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ public static void assertArrayEquals(Object[] expected, Object[] actual, String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} object arrays are deeply equal. *

If both are {@code null}, they are considered equal. *

Nested float arrays are checked as in {@link #assertEquals(float, float)}. *

Nested double arrays are checked as in {@link #assertEquals(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ public static void assertArrayEquals(Object[] expected, Object[] actual, Supplier messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } // --- assertIterableEquals -------------------------------------------- /** * Assert that {@code expected} and {@code actual} iterables are deeply equal. *

Similarly to the check for deep equality in {@link #assertArrayEquals(Object[], Object[])}, * if two iterables are encountered (including {@code expected} and {@code actual}) then their * iterators must return equal elements in the same order as each other. Note: * this means that the iterables do not need to be of the same type. Example:

{@code
	 * import static java.util.Arrays.asList;
	 *  . . .
	 * Iterable i0 = new ArrayList<>(asList(1, 2, 3));
	 * Iterable i1 = new LinkedList<>(asList(1, 2, 3));
	 * assertIterableEquals(i0, i1); // Passes
	 * }
*

If both {@code expected} and {@code actual} are {@code null}, they are considered equal. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[]) */ public static void assertIterableEquals(Iterable expected, Iterable actual) { AssertIterableEquals.assertIterableEquals(expected, actual); } /** * Assert that {@code expected} and {@code actual} iterables are deeply equal. *

Similarly to the check for deep equality in * {@link #assertArrayEquals(Object[], Object[], String)}, if two iterables are encountered * (including {@code expected} and {@code actual}) then their iterators must return equal * elements in the same order as each other. Note: this means that the iterables * do not need to be of the same type. Example:

{@code
	 * import static java.util.Arrays.asList;
	 *  . . .
	 * Iterable i0 = new ArrayList<>(asList(1, 2, 3));
	 * Iterable i1 = new LinkedList<>(asList(1, 2, 3));
	 * assertIterableEquals(i0, i1); // Passes
	 * }
*

If both {@code expected} and {@code actual} are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[], String) */ public static void assertIterableEquals(Iterable expected, Iterable actual, String message) { AssertIterableEquals.assertIterableEquals(expected, actual, message); } /** * Assert that {@code expected} and {@code actual} iterables are deeply equal. *

Similarly to the check for deep equality in * {@link #assertArrayEquals(Object[], Object[], Supplier)}, if two iterables are encountered * (including {@code expected} and {@code actual}) then their iterators must return equal * elements in the same order as each other. Note: this means that the iterables * do not need to be of the same type. Example:

{@code
	 * import static java.util.Arrays.asList;
	 *  . . .
	 * Iterable i0 = new ArrayList<>(asList(1, 2, 3));
	 * Iterable i1 = new LinkedList<>(asList(1, 2, 3));
	 * assertIterableEquals(i0, i1); // Passes
	 * }
*

If both {@code expected} and {@code actual} are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. * * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[], Supplier) */ public static void assertIterableEquals(Iterable expected, Iterable actual, Supplier messageSupplier) { AssertIterableEquals.assertIterableEquals(expected, actual, messageSupplier); } // --- assertLinesMatch ---------------------------------------------------- /** * Assert that {@code expected} list of {@linkplain String}s matches {@code actual} * list. * *

This method differs from other assertions that effectively only check {@link String#equals(Object)}, * in that it uses the following staged matching algorithm: * *

For each pair of expected and actual lines do *

    *
  1. check if {@code expected.equals(actual)} - if yes, continue with next pair
  2. *
  3. otherwise treat {@code expected} as a regular expression and check via * {@link String#matches(String)} - if yes, continue with next pair
  4. *
  5. otherwise check if {@code expected} line is a fast-forward marker, if yes apply * fast-forward actual lines accordingly (see below) and goto 1.
  6. *
* *

A valid fast-forward marker is an expected line that starts and ends with the literal * {@code >>} and contains at least 4 characters. Examples: *

    *
  • {@code >>>>}
    {@code >> stacktrace >>}
    {@code >> single line, non Integer.parse()-able comment >>} *
    Skip arbitrary number of actual lines, until first matching subsequent expected line is found. Any * character between the fast-forward literals are discarded.
  • *
  • {@code ">> 21 >>"} *
    Skip strictly 21 lines. If they can't be skipped for any reason, an assertion error is raised.
  • *
* *

Here is an example showing all three kinds of expected line formats: *

{@code
	 * ls -la /
	 * total [\d]+
	 * drwxr-xr-x  0 root root   512 Jan  1  1970 .
	 * drwxr-xr-x  0 root root   512 Jan  1  1970 ..
	 * drwxr-xr-x  0 root root   512 Apr  5 07:45 bin
	 * >> 4 >>
	 * -rwxr-xr-x  1 root root [\d]+ Jan  1  1970 init
	 * >> M A N Y  M O R E  E N T R I E S >>
	 * drwxr-xr-x  0 root root   512 Sep 22  2017 var
	 * }
*

Fails with a generated failure message describing the difference. */ public static void assertLinesMatch(List expectedLines, List actualLines) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines); } /** * Assert that {@code expected} list of {@linkplain String}s matches {@code actual} * list. * *

Find a detailed description of the matching algorithm in {@link #assertLinesMatch(List, List)}. * *

Fails with the supplied failure {@code message} and the generated message. * * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(List expectedLines, List actualLines, String message) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, message); } /** * Assert that {@code expected} list of {@linkplain String}s matches {@code actual} * list. * *

Find a detailed description of the matching algorithm in {@link #assertLinesMatch(List, List)}. * *

If necessary, a custom failure message will be retrieved lazily from the supplied * {@code messageSupplier}. Fails with the custom failure message prepended to * a generated failure message describing the difference. * * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(List expectedLines, List actualLines, Supplier messageSupplier) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, messageSupplier); } /** * Assert that {@code expected} stream of {@linkplain String}s matches {@code actual} * stream. * *

Find a detailed description of the matching algorithm in {@link #assertLinesMatch(List, List)}. * *

Note: An implementation of this method may consume all lines of both streams eagerly and * delegate the evaluation to {@link #assertLinesMatch(List, List)}. * * @since 5.7 * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(Stream expectedLines, Stream actualLines) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines); } /** * Assert that {@code expected} stream of {@linkplain String}s matches {@code actual} * stream. * *

Find a detailed description of the matching algorithm in {@link #assertLinesMatch(List, List)}. * *

Fails with the supplied failure {@code message} and the generated message. * *

Note: An implementation of this method may consume all lines of both streams eagerly and * delegate the evaluation to {@link #assertLinesMatch(List, List)}. * * @since 5.7 * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(Stream expectedLines, Stream actualLines, String message) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, message); } /** * Assert that {@code expected} stream of {@linkplain String}s matches {@code actual} * stream. * *

Find a detailed description of the matching algorithm in {@link #assertLinesMatch(List, List)}. * *

If necessary, a custom failure message will be retrieved lazily from the supplied * {@code messageSupplier}. Fails with the custom failure message prepended to * a generated failure message describing the difference. * *

Note: An implementation of this method may consume all lines of both streams eagerly and * delegate the evaluation to {@link #assertLinesMatch(List, List)}. * * @since 5.7 * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(Stream expectedLines, Stream actualLines, Supplier messageSupplier) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, messageSupplier); } // --- assertNotEquals ----------------------------------------------------- /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, byte actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, Byte actual) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, byte actual) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, Byte actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, byte actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, Byte actual, String message) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, byte actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, Byte actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(byte unexpected, Byte actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, byte actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Byte unexpected, Byte actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, short actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, Short actual) { AssertNotEquals.assertNotEquals((Short) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, short actual) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, Short actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, short actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, Short actual, String message) { AssertNotEquals.assertNotEquals((Short) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, short actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, Short actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(short unexpected, Short actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Short) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, short actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Short unexpected, Short actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, int actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, Integer actual) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, int actual) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, Integer actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, int actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, Integer actual, String message) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, int actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, Integer actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, int actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(int unexpected, Integer actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, int actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Integer unexpected, Integer actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, long actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, Long actual) { AssertNotEquals.assertNotEquals((Long) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, long actual) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, Long actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, long actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, Long actual, String message) { AssertNotEquals.assertNotEquals((Long) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, long actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, Long actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(long unexpected, Long actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Long) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, long actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Long unexpected, Long actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, Float actual) { AssertNotEquals.assertNotEquals((Float) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, float actual) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, Float actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, Float actual, String message) { AssertNotEquals.assertNotEquals((Float) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, float actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, Float actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, Float actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Float) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, float actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Float unexpected, Float actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual, float delta) { AssertNotEquals.assertNotEquals(unexpected, actual, delta); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual, float delta, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Float#equals(Object)} and {@link Float#compare(float, float)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(float unexpected, float actual, float delta, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, Double actual) { AssertNotEquals.assertNotEquals((Double) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, double actual) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, Double actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, Double actual, String message) { AssertNotEquals.assertNotEquals((Double) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, double actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, Double actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, Double actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Double) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, double actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Double unexpected, Double actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, double delta) { AssertNotEquals.assertNotEquals(unexpected, actual, delta); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, double delta, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, message); } /** * Assert that {@code expected} and {@code actual} are not equal * within the given {@code delta}. * *

Inequality imposed by this method is consistent with * {@link Double#equals(Object)} and {@link Double#compare(double, double)}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, double delta, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, char actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, Character actual) { AssertNotEquals.assertNotEquals((Character) unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, char actual) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, Character actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, char actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, Character actual, String message) { AssertNotEquals.assertNotEquals((Character) unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, char actual, String message) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails with the supplied failure {@code message}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, Character actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(char unexpected, Character actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals((Character) unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, char actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.4 */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(Character unexpected, Character actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails if both are {@code null}. * * @see Object#equals(Object) */ public static void assertNotEquals(Object unexpected, Object actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails if both are {@code null}. * *

Fails with the supplied failure {@code message}. * * @see Object#equals(Object) */ public static void assertNotEquals(Object unexpected, Object actual, String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } /** * Assert that {@code expected} and {@code actual} are not equal. * *

Fails if both are {@code null}. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see Object#equals(Object) */ public static void assertNotEquals(Object unexpected, Object actual, Supplier messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } // --- assertSame ---------------------------------------------------------- /** * Assert that the {@code expected} object and the {@code actual} object * are the same object. *

This method should only be used to assert identity between objects. * To assert equality between two objects or two primitive values, * use one of the {@code assertEquals(...)} methods instead — for example, * use {@code assertEquals(999, 999)} instead of {@code assertSame(999, 999)}. */ public static void assertSame(Object expected, Object actual) { AssertSame.assertSame(expected, actual); } /** * Assert that the {@code expected} object and the {@code actual} object * are the same object. *

This method should only be used to assert identity between objects. * To assert equality between two objects or two primitive values, * use one of the {@code assertEquals(...)} methods instead — for example, * use {@code assertEquals(999, 999)} instead of {@code assertSame(999, 999)}. *

Fails with the supplied failure {@code message}. */ public static void assertSame(Object expected, Object actual, String message) { AssertSame.assertSame(expected, actual, message); } /** * Assert that the {@code expected} object and the {@code actual} object * are the same object. *

This method should only be used to assert identity between objects. * To assert equality between two objects or two primitive values, * use one of the {@code assertEquals(...)} methods instead — for example, * use {@code assertEquals(999, 999)} instead of {@code assertSame(999, 999)}. *

If necessary, the failure message will be retrieved lazily from the supplied * {@code messageSupplier}. */ public static void assertSame(Object expected, Object actual, Supplier messageSupplier) { AssertSame.assertSame(expected, actual, messageSupplier); } // --- assertNotSame ------------------------------------------------------- /** * Assert that the {@code unexpected} object and the {@code actual} * object are not the same object. *

This method should only be used to compare the identity of two * objects. To assert that two objects or two primitive values are not * equal, use one of the {@code assertNotEquals(...)} methods instead. */ public static void assertNotSame(Object unexpected, Object actual) { AssertNotSame.assertNotSame(unexpected, actual); } /** * Assert that the {@code unexpected} object and the {@code actual} * object are not the same object. *

This method should only be used to compare the identity of two * objects. To assert that two objects or two primitive values are not * equal, use one of the {@code assertNotEquals(...)} methods instead. *

Fails with the supplied failure {@code message}. */ public static void assertNotSame(Object unexpected, Object actual, String message) { AssertNotSame.assertNotSame(unexpected, actual, message); } /** * Assert that the {@code unexpected} object and the {@code actual} * object are not the same object. *

This method should only be used to compare the identity of two * objects. To assert that two objects or two primitive values are not * equal, use one of the {@code assertNotEquals(...)} methods instead. *

If necessary, the failure message will be retrieved lazily from the supplied * {@code messageSupplier}. */ public static void assertNotSame(Object unexpected, Object actual, Supplier messageSupplier) { AssertNotSame.assertNotSame(unexpected, actual, messageSupplier); } // --- assertAll ----------------------------------------------------------- /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

See Javadoc for {@link #assertAll(String, Stream)} for an explanation of this * method's exception handling semantics. * * @see #assertAll(String, Executable...) * @see #assertAll(Collection) * @see #assertAll(String, Collection) * @see #assertAll(Stream) * @see #assertAll(String, Stream) */ public static void assertAll(Executable... executables) throws MultipleFailuresError { AssertAll.assertAll(executables); } /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

See Javadoc for {@link #assertAll(String, Stream)} for an explanation of this * method's exception handling semantics. * * @see #assertAll(Executable...) * @see #assertAll(Collection) * @see #assertAll(Stream) * @see #assertAll(String, Collection) * @see #assertAll(String, Stream) */ public static void assertAll(String heading, Executable... executables) throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

See Javadoc for {@link #assertAll(String, Stream)} for an explanation of this * method's exception handling semantics. * * @see #assertAll(Executable...) * @see #assertAll(String, Executable...) * @see #assertAll(String, Collection) * @see #assertAll(Stream) * @see #assertAll(String, Stream) */ public static void assertAll(Collection executables) throws MultipleFailuresError { AssertAll.assertAll(executables); } /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

See Javadoc for {@link #assertAll(String, Stream)} for an explanation of this * method's exception handling semantics. * * @see #assertAll(Executable...) * @see #assertAll(String, Executable...) * @see #assertAll(Collection) * @see #assertAll(Stream) * @see #assertAll(String, Stream) */ public static void assertAll(String heading, Collection executables) throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

See Javadoc for {@link #assertAll(String, Stream)} for an explanation of this * method's exception handling semantics. * * @see #assertAll(Executable...) * @see #assertAll(String, Executable...) * @see #assertAll(Collection) * @see #assertAll(String, Collection) * @see #assertAll(String, Stream) */ public static void assertAll(Stream executables) throws MultipleFailuresError { AssertAll.assertAll(executables); } /** * Assert that all supplied {@code executables} do not throw * exceptions. * *

If any supplied {@link Executable} throws an exception (i.e., a {@link Throwable} * or any subclass thereof), all remaining {@code executables} will still be executed, * and all exceptions will be aggregated and reported in a {@link MultipleFailuresError}. * In addition, all aggregated exceptions will be added as {@linkplain * Throwable#addSuppressed(Throwable) suppressed exceptions} to the * {@code MultipleFailuresError}. However, if an {@code executable} throws an * unrecoverable exception — for example, an {@link OutOfMemoryError} * — execution will halt immediately, and the unrecoverable exception will be * rethrown as is but masked as an unchecked exception. * *

The supplied {@code heading} will be included in the message string for the * {@code MultipleFailuresError}. * * @see #assertAll(Executable...) * @see #assertAll(String, Executable...) * @see #assertAll(Collection) * @see #assertAll(String, Collection) * @see #assertAll(Stream) */ public static void assertAll(String heading, Stream executables) throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } // --- assert exceptions --------------------------------------------------- // --- executable --- /** * Assert that execution of the supplied {@code executable} throws * an exception of exactly the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertThrowsExactly(Class expectedType, Executable executable) { return AssertThrowsExactly.assertThrowsExactly(expectedType, executable); } /** * Assert that execution of the supplied {@code executable} throws * an exception of exactly the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. * *

Fails with the supplied failure {@code message}. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertThrowsExactly(Class expectedType, Executable executable, String message) { return AssertThrowsExactly.assertThrowsExactly(expectedType, executable, message); } /** * Assert that execution of the supplied {@code executable} throws * an exception of exactly the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertThrowsExactly(Class expectedType, Executable executable, Supplier messageSupplier) { return AssertThrowsExactly.assertThrowsExactly(expectedType, executable, messageSupplier); } /** * Assert that execution of the supplied {@code executable} throws * an exception of the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. */ public static T assertThrows(Class expectedType, Executable executable) { return AssertThrows.assertThrows(expectedType, executable); } /** * Assert that execution of the supplied {@code executable} throws * an exception of the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. * *

Fails with the supplied failure {@code message}. */ public static T assertThrows(Class expectedType, Executable executable, String message) { return AssertThrows.assertThrows(expectedType, executable, message); } /** * Assert that execution of the supplied {@code executable} throws * an exception of the {@code expectedType} and return the exception. * *

If no exception is thrown, or if an exception of a different type is * thrown, this method will fail. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * *

If you do not want to perform additional checks on the exception instance, * ignore the return value. */ public static T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier) { return AssertThrows.assertThrows(expectedType, executable, messageSupplier); } // --- executable --- /** * Assert that execution of the supplied {@code executable} does * not throw any kind of {@linkplain Throwable exception}. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static void assertDoesNotThrow(Executable executable) { AssertDoesNotThrow.assertDoesNotThrow(executable); } /** * Assert that execution of the supplied {@code executable} does * not throw any kind of {@linkplain Throwable exception}. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * *

Fails with the supplied failure {@code message}. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static void assertDoesNotThrow(Executable executable, String message) { AssertDoesNotThrow.assertDoesNotThrow(executable, message); } /** * Assert that execution of the supplied {@code executable} does * not throw any kind of {@linkplain Throwable exception}. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static void assertDoesNotThrow(Executable executable, Supplier messageSupplier) { AssertDoesNotThrow.assertDoesNotThrow(executable, messageSupplier); } // --- supplier --- /** * Assert that execution of the supplied {@code supplier} does * not throw any kind of {@linkplain Throwable exception}. * *

If the assertion passes, the {@code supplier}'s result will be returned. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static T assertDoesNotThrow(ThrowingSupplier supplier) { return AssertDoesNotThrow.assertDoesNotThrow(supplier); } /** * Assert that execution of the supplied {@code supplier} does * not throw any kind of {@linkplain Throwable exception}. * *

If the assertion passes, the {@code supplier}'s result will be returned. * *

Fails with the supplied failure {@code message}. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static T assertDoesNotThrow(ThrowingSupplier supplier, String message) { return AssertDoesNotThrow.assertDoesNotThrow(supplier, message); } /** * Assert that execution of the supplied {@code supplier} does * not throw any kind of {@linkplain Throwable exception}. * *

If the assertion passes, the {@code supplier}'s result will be returned. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * *

Usage Note

*

Although any exception thrown from a test method will cause the test * to fail, there are certain use cases where it can be beneficial * to explicitly assert that an exception is not thrown for a given code * block within a test method. * * @since 5.2 */ @API(status = STABLE, since = "5.2") public static T assertDoesNotThrow(ThrowingSupplier supplier, Supplier messageSupplier) { return AssertDoesNotThrow.assertDoesNotThrow(supplier, messageSupplier); } // --- assertTimeout ------------------------------------------------------- // --- executable --- /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

Note: the {@code executable} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code executable} will * not be preemptively aborted if the timeout is exceeded. * * @see #assertTimeout(Duration, Executable, String) * @see #assertTimeout(Duration, Executable, Supplier) * @see #assertTimeout(Duration, ThrowingSupplier) * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable) */ public static void assertTimeout(Duration timeout, Executable executable) { AssertTimeout.assertTimeout(timeout, executable); } /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

Note: the {@code executable} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code executable} will * not be preemptively aborted if the timeout is exceeded. * *

Fails with the supplied failure {@code message}. * * @see #assertTimeout(Duration, Executable) * @see #assertTimeout(Duration, Executable, Supplier) * @see #assertTimeout(Duration, ThrowingSupplier) * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, String) */ public static void assertTimeout(Duration timeout, Executable executable, String message) { AssertTimeout.assertTimeout(timeout, executable, message); } /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

Note: the {@code executable} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code executable} will * not be preemptively aborted if the timeout is exceeded. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see #assertTimeout(Duration, Executable) * @see #assertTimeout(Duration, Executable, String) * @see #assertTimeout(Duration, ThrowingSupplier) * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) */ public static void assertTimeout(Duration timeout, Executable executable, Supplier messageSupplier) { AssertTimeout.assertTimeout(timeout, executable, messageSupplier); } // --- supplier --- /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

Note: the {@code supplier} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code supplier} will * not be preemptively aborted if the timeout is exceeded. * * @see #assertTimeout(Duration, Executable) * @see #assertTimeout(Duration, Executable, String) * @see #assertTimeout(Duration, Executable, Supplier) * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable) */ public static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { return AssertTimeout.assertTimeout(timeout, supplier); } /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

Note: the {@code supplier} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code supplier} will * not be preemptively aborted if the timeout is exceeded. * *

Fails with the supplied failure {@code message}. * * @see #assertTimeout(Duration, Executable) * @see #assertTimeout(Duration, Executable, String) * @see #assertTimeout(Duration, Executable, Supplier) * @see #assertTimeout(Duration, ThrowingSupplier) * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, String) */ public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, String message) { return AssertTimeout.assertTimeout(timeout, supplier, message); } /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

Note: the {@code supplier} will be executed in the same thread as that * of the calling code. Consequently, execution of the {@code supplier} will * not be preemptively aborted if the timeout is exceeded. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see #assertTimeout(Duration, Executable) * @see #assertTimeout(Duration, Executable, String) * @see #assertTimeout(Duration, Executable, Supplier) * @see #assertTimeout(Duration, ThrowingSupplier) * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) */ public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier) { return AssertTimeout.assertTimeout(timeout, supplier, messageSupplier); } // --- executable - preemptively --- /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable) */ public static void assertTimeoutPreemptively(Duration timeout, Executable executable) { AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, executable); } /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

Fails with the supplied failure {@code message}. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable, String) */ public static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message) { AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, executable, message); } /** * Assert that execution of the supplied {@code executable} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable, Supplier) */ public static void assertTimeoutPreemptively(Duration timeout, Executable executable, Supplier messageSupplier) { AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, executable, messageSupplier); } // --- supplier - preemptively --- /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

If the assertion passes then the {@code supplier}'s result is returned. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable) */ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier); } /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

Fails with the supplied failure {@code message}. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable, String) */ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, String message) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, message); } /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, Executable, Supplier) */ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, messageSupplier); } /** * Assert that execution of the supplied {@code supplier} * completes before the given {@code timeout} is exceeded. * *

See the {@linkplain Assertions Preemptive Timeouts} section of the * class-level Javadoc for further details. * *

If the assertion passes then the {@code supplier}'s result is returned. * *

In the case the assertion does not pass, the supplied * {@link TimeoutFailureFactory} is invoked to create an exception which is * then thrown. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @see #assertTimeoutPreemptively(Duration, Executable) * @see #assertTimeoutPreemptively(Duration, Executable, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier) * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, Executable, Supplier) */ @API(status = INTERNAL, since = "5.9.1") public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier, TimeoutFailureFactory failureFactory) throws E { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, messageSupplier, failureFactory); } // --- assertInstanceOf ---------------------------------------------------- /** * Assert that the supplied {@code actualValue} is an instance of the * {@code expectedType}. * *

Like the {@code instanceof} operator a {@code null} value is not * considered to be of the {@code expectedType} and does not pass the assertion. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertInstanceOf(Class expectedType, Object actualValue) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue); } /** * Assert that the supplied {@code actualValue} is an instance of the * {@code expectedType}. * *

Like the {@code instanceof} operator a {@code null} value is not * considered to be of the {@code expectedType} and does not pass the assertion. * *

Fails with the supplied failure {@code message}. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertInstanceOf(Class expectedType, Object actualValue, String message) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue, message); } /** * Assert that the supplied {@code actualValue} is an instance of the * {@code expectedType}. * *

Like the {@code instanceof} operator a {@code null} value is not * considered to be of the {@code expectedType} and does not pass the assertion. * *

If necessary, the failure message will be retrieved lazily from the * supplied {@code messageSupplier}. * * @since 5.8 */ @API(status = STABLE, since = "5.10") public static T assertInstanceOf(Class expectedType, Object actualValue, Supplier messageSupplier) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue, messageSupplier); } /** * Factory for timeout failures. * * @param The type of error or exception created * @since 5.9.1 * @see Assertions#assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier, TimeoutFailureFactory) */ @API(status = INTERNAL, since = "5.9.1") public interface TimeoutFailureFactory { /** * Create a failure for the given timeout, message, and cause. * * @return timeout failure; never {@code null} */ T createTimeoutFailure(Duration timeout, Supplier messageSupplier, Throwable cause); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assumptions.java000066400000000000000000000260531455764576500306140ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.StringUtils; import org.opentest4j.TestAbortedException; /** * {@code Assumptions} is a collection of utility methods that support * conditional test execution based on assumptions. * *

In direct contrast to failed {@linkplain Assertions assertions}, * failed assumptions do not result in a test failure; rather, * a failed assumption results in a test being aborted. * *

Assumptions are typically used whenever it does not make sense to * continue execution of a given test method — for example, if the * test depends on something that does not exist in the current runtime * environment. * *

Although it is technically possible to extend this class, extension is * strongly discouraged. The JUnit Team highly recommends that the methods * defined in this class be used via static imports. * * @since 5.0 * @see TestAbortedException * @see Assertions */ @API(status = STABLE, since = "5.0") public class Assumptions { /** * Protected constructor allowing subclassing but not direct instantiation. * * @since 5.3 */ protected Assumptions() { /* no-op */ } // --- assumeTrue ---------------------------------------------------------- /** * Validate the given assumption. * * @param assumption the assumption to validate * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(boolean assumption) throws TestAbortedException { assumeTrue(assumption, "assumption is not true"); } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(BooleanSupplier assumptionSupplier) throws TestAbortedException { assumeTrue(assumptionSupplier.getAsBoolean(), "assumption is not true"); } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @param message the message to be included in the {@code TestAbortedException} * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException { assumeTrue(assumptionSupplier.getAsBoolean(), message); } /** * Validate the given assumption. * * @param assumption the assumption to validate * @param messageSupplier the supplier of the message to be included in * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(boolean assumption, Supplier messageSupplier) throws TestAbortedException { if (!assumption) { throwAssumptionFailed(messageSupplier.get()); } } /** * Validate the given assumption. * * @param assumption the assumption to validate * @param message the message to be included in the {@code TestAbortedException} * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(boolean assumption, String message) throws TestAbortedException { if (!assumption) { throwAssumptionFailed(message); } } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @param messageSupplier the supplier of the message to be included in * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ public static void assumeTrue(BooleanSupplier assumptionSupplier, Supplier messageSupplier) throws TestAbortedException { assumeTrue(assumptionSupplier.getAsBoolean(), messageSupplier); } // --- assumeFalse --------------------------------------------------------- /** * Validate the given assumption. * * @param assumption the assumption to validate * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(boolean assumption) throws TestAbortedException { assumeFalse(assumption, "assumption is not false"); } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(BooleanSupplier assumptionSupplier) throws TestAbortedException { assumeFalse(assumptionSupplier.getAsBoolean(), "assumption is not false"); } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @param message the message to be included in the {@code TestAbortedException} * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException { assumeFalse(assumptionSupplier.getAsBoolean(), message); } /** * Validate the given assumption. * * @param assumption the assumption to validate * @param messageSupplier the supplier of the message to be included in * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(boolean assumption, Supplier messageSupplier) throws TestAbortedException { if (assumption) { throwAssumptionFailed(messageSupplier.get()); } } /** * Validate the given assumption. * * @param assumption the assumption to validate * @param message the message to be included in the {@code TestAbortedException} * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(boolean assumption, String message) throws TestAbortedException { if (assumption) { throwAssumptionFailed(message); } } /** * Validate the given assumption. * * @param assumptionSupplier the supplier of the assumption to validate * @param messageSupplier the supplier of the message to be included in * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ public static void assumeFalse(BooleanSupplier assumptionSupplier, Supplier messageSupplier) throws TestAbortedException { assumeFalse(assumptionSupplier.getAsBoolean(), messageSupplier); } // --- assumingThat -------------------------------------------------------- /** * Execute the supplied {@link Executable}, but only if the supplied * assumption is valid. * *

Unlike the other assumption methods, this method will not abort the test. * If the assumption is invalid, this method does nothing. If the assumption is * valid and the {@code executable} throws an exception, it will be treated like * a regular test failure. That exception will be rethrown as is * but {@link ExceptionUtils#throwAsUncheckedException masked} as an unchecked * exception. * * @param assumptionSupplier the supplier of the assumption to validate * @param executable the block of code to execute if the assumption is valid * @see #assumingThat(boolean, Executable) */ public static void assumingThat(BooleanSupplier assumptionSupplier, Executable executable) { assumingThat(assumptionSupplier.getAsBoolean(), executable); } /** * Execute the supplied {@link Executable}, but only if the supplied * assumption is valid. * *

Unlike the other assumption methods, this method will not abort the test. * If the assumption is invalid, this method does nothing. If the assumption is * valid and the {@code executable} throws an exception, it will be treated like * a regular test failure. That exception will be rethrown as is * but {@link ExceptionUtils#throwAsUncheckedException masked} as an unchecked * exception. * * @param assumption the assumption to validate * @param executable the block of code to execute if the assumption is valid * @see #assumingThat(BooleanSupplier, Executable) */ public static void assumingThat(boolean assumption, Executable executable) { if (assumption) { try { executable.execute(); } catch (Throwable t) { ExceptionUtils.throwAsUncheckedException(t); } } } // --- abort --------------------------------------------------------------- /** * Abort the test without a message. * *

Although aborting with an explicit message is recommended, this may be * useful when maintaining legacy code. * *

See Javadoc for {@link #abort(String)} for an explanation of this * method's generic return type {@code V}. * * @throws TestAbortedException always * @since 5.9 */ @API(status = STABLE, since = "5.9") public static V abort() { throw new TestAbortedException(); } /** * Abort the test with the given {@code message}. * *

The generic return type {@code V} allows this method to be used * directly as a single-statement lambda expression, thereby avoiding the * need to implement a code block with an explicit return value. Since this * method throws a {@link TestAbortedException} before its return statement, * this method never actually returns a value to its caller. The following * example demonstrates how this may be used in practice. * *

{@code
	 * Stream.of().map(entry -> abort("assumption not met"));
	 * }
* * @param message the message to be included in the {@code TestAbortedException} * @throws TestAbortedException always * @since 5.9 */ @API(status = STABLE, since = "5.9") public static V abort(String message) { throw new TestAbortedException(message); } /** * Abort the test with the supplied message. * *

See Javadoc for {@link #abort(String)} for an explanation of this * method's generic return type {@code V}. * * @param messageSupplier the supplier of the message to be included in the * {@code TestAbortedException} * @throws TestAbortedException always * @since 5.9 */ @API(status = STABLE, since = "5.9") public static V abort(Supplier messageSupplier) { throw new TestAbortedException(messageSupplier.get()); } private static void throwAssumptionFailed(String message) { throw new TestAbortedException( StringUtils.isNotBlank(message) ? "Assumption failed: " + message : "Assumption failed"); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeAll.java000066400000000000000000000105551455764576500301220ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @BeforeAll} is used to signal that the annotated method should be * executed before all tests in the current test class. * *

In contrast to {@link BeforeEach @BeforeEach} methods, {@code @BeforeAll} * methods are only executed once for a given test class. * *

Method Signatures

* *

{@code @BeforeAll} methods must have a {@code void} return type and must * be {@code static} by default. Consequently, {@code @BeforeAll} methods are * not supported in {@link Nested @Nested} test classes or as interface * default methods unless the test class is annotated with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * However, beginning with Java 16 {@code @BeforeAll} methods may be declared as * {@code static} in {@link Nested @Nested} test classes, and the * {@code Lifecycle.PER_CLASS} restriction no longer applies. {@code @BeforeAll} * methods may optionally declare parameters to be resolved by * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolvers}. * *

Using {@code private} visibility for {@code @BeforeAll} methods is * strongly discouraged and will be disallowed in a future release. * *

Inheritance and Execution Order

* *

{@code @BeforeAll} methods are inherited from superclasses as long as * they are not hidden (default mode with {@code static} modifier), * overridden, or superseded (i.e., replaced based on * signature only, irrespective of Java's visibility rules). Furthermore, * {@code @BeforeAll} methods from superclasses will be executed before * {@code @BeforeAll} methods in subclasses. * *

Similarly, {@code @BeforeAll} methods declared in an interface are * inherited as long as they are not hidden or overridden, * and {@code @BeforeAll} methods from an interface will be executed before * {@code @BeforeAll} methods in the class that implements the interface. * *

JUnit Jupiter does not guarantee the execution order of multiple * {@code @BeforeAll} methods that are declared within a single test class or * test interface. While it may at times appear that these methods are invoked * in alphabetical order, they are in fact sorted using an algorithm that is * deterministic but intentionally non-obvious. * *

In addition, {@code @BeforeAll} methods are in no way linked to * {@code @AfterAll} methods. Consequently, there are no guarantees with regard * to their wrapping behavior. For example, given two * {@code @BeforeAll} methods {@code createA()} and {@code createB()} as well as * two {@code @AfterAll} methods {@code destroyA()} and {@code destroyB()}, the * order in which the {@code @BeforeAll} methods are executed (e.g. * {@code createA()} before {@code createB()}) does not imply any order for the * seemingly corresponding {@code @AfterAll} methods. In other words, * {@code destroyA()} might be called before or after * {@code destroyB()}. The JUnit Team therefore recommends that developers * declare at most one {@code @BeforeAll} method and at most one * {@code @AfterAll} method per test class or test interface unless there are no * dependencies between the {@code @BeforeAll} methods or between the * {@code @AfterAll} methods. * *

Composition

* *

{@code @BeforeAll} may be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @BeforeAll}. * * @since 5.0 * @see AfterAll * @see BeforeEach * @see AfterEach * @see Test * @see TestFactory * @see TestInstance */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface BeforeAll { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeEach.java000066400000000000000000000074501455764576500302520ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @BeforeEach} is used to signal that the annotated method should be * executed before each {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, * and {@code @TestTemplate} method in the current test class. * *

Method Signatures

* *

{@code @BeforeEach} methods must have a {@code void} return type and must * not be {@code static}. Using {@code private} visibility is strongly * discouraged and will be disallowed in a future release. * They may optionally declare parameters to be resolved by * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolvers}. * *

Inheritance and Execution Order

* *

{@code @BeforeEach} methods are inherited from superclasses as long as they * are not overridden or superseded (i.e., replaced based on * signature only, irrespective of Java's visibility rules). Furthermore, * {@code @BeforeEach} methods from superclasses will be executed before * {@code @BeforeEach} methods in subclasses. * *

Similarly, {@code @BeforeEach} methods declared as interface default * methods are inherited as long as they are not overridden, and * {@code @BeforeEach} default methods will be executed before {@code @BeforeEach} * methods in the class that implements the interface. * *

JUnit Jupiter does not guarantee the execution order of multiple * {@code @BeforeEach} methods that are declared within a single test class or * test interface. While it may at times appear that these methods are invoked * in alphabetical order, they are in fact sorted using an algorithm that is * deterministic but intentionally non-obvious. * *

In addition, {@code @BeforeEach} methods are in no way linked to * {@code @AfterEach} methods. Consequently, there are no guarantees with regard * to their wrapping behavior. For example, given two * {@code @BeforeEach} methods {@code createA()} and {@code createB()} as well * as two {@code @AfterEach} methods {@code destroyA()} and {@code destroyB()}, * the order in which the {@code @BeforeEach} methods are executed (e.g. * {@code createA()} before {@code createB()}) does not imply any order for the * seemingly corresponding {@code @AfterEach} methods. In other words, * {@code destroyA()} might be called before or after * {@code destroyB()}. The JUnit Team therefore recommends that developers * declare at most one {@code @BeforeEach} method and at most one * {@code @AfterEach} method per test class or test interface unless there are * no dependencies between the {@code @BeforeEach} methods or between the * {@code @AfterEach} methods. * *

Composition

* *

{@code @BeforeEach} may be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @BeforeEach}. * * @since 5.0 * @see AfterEach * @see BeforeAll * @see AfterAll * @see Test * @see RepeatedTest * @see TestFactory * @see TestTemplate */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface BeforeEach { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassDescriptor.java000066400000000000000000000052431455764576500313710ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code ClassDescriptor} encapsulates functionality for a given {@link Class}. * * @since 5.8 * @see ClassOrdererContext */ @API(status = STABLE, since = "5.10") public interface ClassDescriptor { /** * Get the class for this descriptor. * * @return the class; never {@code null} */ Class getTestClass(); /** * Get the display name for this descriptor's {@link #getTestClass() class}. * * @return the display name for this descriptor's class; never {@code null} * or blank */ String getDisplayName(); /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the {@link Class} for * this descriptor. * * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @see #findAnnotation(Class) * @see #findRepeatableAnnotations(Class) */ boolean isAnnotated(Class annotationType); /** * Find the first annotation of {@code annotationType} that is either * present or meta-present on the {@link Class} for * this descriptor. * * @param the annotation type * @param annotationType the annotation type to search for; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @see #isAnnotated(Class) * @see #findRepeatableAnnotations(Class) */ Optional findAnnotation(Class annotationType); /** * Find all repeatable {@linkplain Annotation annotations} of * {@code annotationType} that are either present or * meta-present on the {@link Class} for this descriptor. * * @param the annotation type * @param annotationType the repeatable annotation type to search for; never * {@code null} * @return the list of all such annotations found; neither {@code null} nor * mutable, but potentially empty * @see #isAnnotated(Class) * @see #findAnnotation(Class) * @see java.lang.annotation.Repeatable */ List findRepeatableAnnotations(Class annotationType); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassOrderer.java000066400000000000000000000221171455764576500306540ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.Comparator.comparingInt; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; import java.util.Comparator; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * {@code ClassOrderer} defines the API for ordering top-level test classes and * {@link Nested @Nested} test classes. * *

In this context, the term "test class" refers to any class containing methods * annotated with {@code @Test}, {@code @RepeatedTest}, {@code @ParameterizedTest}, * {@code @TestFactory}, or {@code @TestTemplate}. * *

Top-level test classes will be ordered relative to each other; whereas, * {@code @Nested} test classes will be ordered relative to other {@code @Nested} * test classes sharing the same {@linkplain Class#getEnclosingClass() enclosing * class}. * *

A {@link ClassOrderer} can be configured globally for the entire * test suite via the {@value #DEFAULT_ORDER_PROPERTY_NAME} configuration * parameter (see the User Guide for details) or locally for * {@link Nested @Nested} test classes via the {@link TestClassOrder @TestClassOrder} * annotation. * *

Built-in Implementations

* *

JUnit Jupiter provides the following built-in {@code ClassOrderer} * implementations. * *

    *
  • {@link ClassOrderer.ClassName}
  • *
  • {@link ClassOrderer.DisplayName}
  • *
  • {@link ClassOrderer.OrderAnnotation}
  • *
  • {@link ClassOrderer.Random}
  • *
* * @since 5.8 * @see TestClassOrder * @see ClassOrdererContext * @see #orderClasses(ClassOrdererContext) * @see MethodOrderer */ @API(status = STABLE, since = "5.10") public interface ClassOrderer { /** * Property name used to set the default class orderer class name: {@value} * *

Supported Values

* *

Supported values include fully qualified class names for types that * implement {@link org.junit.jupiter.api.ClassOrderer}. * *

If not specified, test classes are not ordered unless test classes are * annotated with {@link TestClassOrder @TestClassOrder}. * * @since 5.8 */ @API(status = STABLE, since = "5.9") String DEFAULT_ORDER_PROPERTY_NAME = "junit.jupiter.testclass.order.default"; /** * Order the classes encapsulated in the supplied {@link ClassOrdererContext}. * *

The classes to order or sort are made indirectly available via * {@link ClassOrdererContext#getClassDescriptors()}. Since this method * has a {@code void} return type, the list of class descriptors must be * modified directly. * *

For example, a simplified implementation of the {@link ClassOrderer.Random} * {@code ClassOrderer} might look like the following. * *

	 * public void orderClasses(ClassOrdererContext context) {
	 *     Collections.shuffle(context.getClassDescriptors());
	 * }
	 * 
* * @param context the {@code ClassOrdererContext} containing the * {@linkplain ClassDescriptor class descriptors} to order; never {@code null} */ void orderClasses(ClassOrdererContext context); /** * {@code ClassOrderer} that sorts classes alphanumerically based on their * fully qualified names using {@link String#compareTo(String)}. */ class ClassName implements ClassOrderer { public ClassName() { } /** * Sort the classes encapsulated in the supplied * {@link ClassOrdererContext} alphanumerically based on their fully * qualified names. */ @Override public void orderClasses(ClassOrdererContext context) { context.getClassDescriptors().sort(comparator); } private static final Comparator comparator = Comparator.comparing( descriptor -> descriptor.getTestClass().getName()); } /** * {@code ClassOrderer} that sorts classes alphanumerically based on their * display names using {@link String#compareTo(String)} */ class DisplayName implements ClassOrderer { public DisplayName() { } /** * Sort the classes encapsulated in the supplied * {@link ClassOrdererContext} alphanumerically based on their display * names. */ @Override public void orderClasses(ClassOrdererContext context) { context.getClassDescriptors().sort(comparator); } private static final Comparator comparator = Comparator.comparing( ClassDescriptor::getDisplayName); } /** * {@code ClassOrderer} that sorts classes based on the {@link Order @Order} * annotation. * *

Any classes that are assigned the same order value will be sorted * arbitrarily adjacent to each other. * *

Any classes not annotated with {@code @Order} will be assigned the * {@linkplain Order#DEFAULT default order} value which will effectively cause them * to appear at the end of the sorted list, unless certain classes are assigned * an explicit order value greater than the default order value. Any classes * assigned an explicit order value greater than the default order value will * appear after non-annotated classes in the sorted list. */ class OrderAnnotation implements ClassOrderer { public OrderAnnotation() { } /** * Sort the classes encapsulated in the supplied * {@link ClassOrdererContext} based on the {@link Order @Order} * annotation. */ @Override public void orderClasses(ClassOrdererContext context) { context.getClassDescriptors().sort(comparingInt(OrderAnnotation::getOrder)); } private static int getOrder(ClassDescriptor descriptor) { return descriptor.findAnnotation(Order.class).map(Order::value).orElse(Order.DEFAULT); } } /** * {@code ClassOrderer} that orders classes pseudo-randomly. * *

Custom Seed

* *

By default, the random seed used for ordering classes is the * value returned by {@link System#nanoTime()} during static initialization * of this class. In order to support repeatable builds, the value of the * default random seed is logged at {@code CONFIG} level. In addition, a * custom seed (potentially the default seed from the previous test plan * execution) may be specified via the {@value Random#RANDOM_SEED_PROPERTY_NAME} * configuration parameter which can be supplied via the {@code Launcher} * API, build tools (e.g., Gradle and Maven), a JVM system property, or the JUnit * Platform configuration file (i.e., a file named {@code junit-platform.properties} * in the root of the class path). Consult the User Guide for further information. * * @see Random#RANDOM_SEED_PROPERTY_NAME * @see java.util.Random */ class Random implements ClassOrderer { private static final Logger logger = LoggerFactory.getLogger(Random.class); /** * Default seed, which is generated during initialization of this class * via {@link System#nanoTime()} for reproducibility of tests. */ private static final long DEFAULT_SEED; static { DEFAULT_SEED = System.nanoTime(); logger.config(() -> "ClassOrderer.Random default seed: " + DEFAULT_SEED); } /** * Property name used to set the random seed used by this * {@code ClassOrderer}: {@value} * *

The same property is used by {@link MethodOrderer.Random} for * consistency between the two random orderers. * *

Supported Values

* *

Supported values include any string that can be converted to a * {@link Long} via {@link Long#valueOf(String)}. * *

If not specified or if the specified value cannot be converted to * a {@link Long}, the default random seed will be used (see the * {@linkplain Random class-level Javadoc} for details). * * @see MethodOrderer.Random */ public static final String RANDOM_SEED_PROPERTY_NAME = MethodOrderer.Random.RANDOM_SEED_PROPERTY_NAME; public Random() { } /** * Order the classes encapsulated in the supplied * {@link ClassOrdererContext} pseudo-randomly. */ @Override public void orderClasses(ClassOrdererContext context) { Collections.shuffle(context.getClassDescriptors(), new java.util.Random(getCustomSeed(context).orElse(DEFAULT_SEED))); } private Optional getCustomSeed(ClassOrdererContext context) { return context.getConfigurationParameter(RANDOM_SEED_PROPERTY_NAME).map(configurationParameter -> { Long seed = null; try { seed = Long.valueOf(configurationParameter); logger.config( () -> String.format("Using custom seed for configuration parameter [%s] with value [%s].", RANDOM_SEED_PROPERTY_NAME, configurationParameter)); } catch (NumberFormatException ex) { logger.warn(ex, () -> String.format( "Failed to convert configuration parameter [%s] with value [%s] to a long. " + "Using default seed [%s] as fallback.", RANDOM_SEED_PROPERTY_NAME, configurationParameter, DEFAULT_SEED)); } return seed; }); } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassOrdererContext.java000066400000000000000000000032151455764576500322170ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code ClassOrdererContext} encapsulates the context in which * a {@link ClassOrderer} will be invoked. * * @since 5.8 * @see ClassOrderer * @see ClassDescriptor */ @API(status = STABLE, since = "5.10") public interface ClassOrdererContext { /** * Get the list of {@linkplain ClassDescriptor class descriptors} to * order. * * @return the list of class descriptors; never {@code null} */ List getClassDescriptors(); /** * Get the configuration parameter stored under the specified {@code key}. * *

If no such key is present in the {@code ConfigurationParameters} for * the JUnit Platform, an attempt will be made to look up the value as a * JVM system property. If no such system property exists, an attempt will * be made to look up the value in the JUnit Platform properties file. * * @param key the key to look up; never {@code null} or blank * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @see System#getProperty(String) * @see org.junit.platform.engine.ConfigurationParameters */ Optional getConfigurationParameter(String key); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Disabled.java000066400000000000000000000052111455764576500277670ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Disabled} is used to signal that the annotated test class or * test method is currently disabled and should not be executed. * *

{@code @Disabled} may optionally be declared with a {@linkplain #value * reason} to document why the annotated test class or test method is disabled. * *

When applied at the class level, all test methods within that class * are automatically disabled as well. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

When applied at the method level, the presence of this annotation does not * prevent the test class from being instantiated. Rather, it prevents the * execution of the test method and method-level lifecycle callbacks such as * {@code @BeforeEach} methods, {@code @AfterEach} methods, and corresponding * extension APIs. * * @since 5.0 * @see #value * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.extension.ExecutionCondition */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface Disabled { /** * The reason this annotated test class or test method is disabled. */ String value() default ""; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayName.java000066400000000000000000000025561455764576500304770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @DisplayName} is used to declare a {@linkplain #value custom display * name} for the annotated test class or test method. * *

Display names are typically used for test reporting in IDEs and build * tools and may contain spaces, special characters, and even emoji. * * @since 5.0 * @see Test * @see Tag * @see TestInfo * @see DisplayNameGeneration * @see DisplayNameGenerator */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface DisplayName { /** * Custom display name for the annotated class or method. * * @return a custom display name; never blank or consisting solely of * whitespace */ String value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGeneration.java000066400000000000000000000034651455764576500325130ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @DisplayNameGeneration} is used to declare a custom display name * generator for the annotated test class. * *

This annotation is inherited from superclasses and implemented * interfaces. It is also inherited from {@linkplain Class#getEnclosingClass() * enclosing classes} for {@link Nested @Nested} test classes. * *

As an alternative to {@code @DisplayNameGeneration}, a global * {@link DisplayNameGenerator} can be configured for the entire test suite via * the {@value DisplayNameGenerator#DEFAULT_GENERATOR_PROPERTY_NAME} configuration parameter. See * the User Guide for details. Note, however, that a {@code @DisplayNameGeneration} * declaration always overrides a global {@code DisplayNameGenerator}. * * @since 5.4 * @see DisplayName * @see DisplayNameGenerator * @see IndicativeSentencesGeneration */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.7") public @interface DisplayNameGeneration { /** * Custom display name generator. * * @return custom display name generator class */ Class value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java000066400000000000000000000333241455764576500323430ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.support.ModifierSupport.isStatic; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.reflect.Method; import java.util.Optional; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code DisplayNameGenerator} defines the SPI for generating display names * programmatically. * *

Display names are typically used for test reporting in IDEs and build * tools and may contain spaces, special characters, and even emoji. * *

Concrete implementations must have a default constructor. * *

A {@link DisplayNameGenerator} can be configured globally for the * entire test suite via the {@value #DEFAULT_GENERATOR_PROPERTY_NAME} * configuration parameter (see the User Guide for details) or locally * for a test class via the {@link DisplayNameGeneration @DisplayNameGeneration} * annotation. * *

Built-in Implementations

*
    *
  • {@link Standard}
  • *
  • {@link Simple}
  • *
  • {@link ReplaceUnderscores}
  • *
  • {@link IndicativeSentences}
  • *
* * @since 5.4 * @see DisplayName @DisplayName * @see DisplayNameGeneration @DisplayNameGeneration */ @API(status = STABLE, since = "5.7") public interface DisplayNameGenerator { /** * Property name used to set the default display name generator class name: * {@value} * *

Supported Values

* *

Supported values include fully qualified class names for types that * implement {@link DisplayNameGenerator}. * *

If not specified, the default is * {@link DisplayNameGenerator.Standard}. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_GENERATOR_PROPERTY_NAME = "junit.jupiter.displayname.generator.default"; /** * Generate a display name for the given top-level or {@code static} nested test class. * *

If it returns {@code null}, the default display name generator will be used instead. * * @param testClass the class to generate a name for; never {@code null} * @return the display name for the class; never blank */ String generateDisplayNameForClass(Class testClass); /** * Generate a display name for the given {@link Nested @Nested} inner test class. * *

If it returns {@code null}, the default display name generator will be used instead. * * @param nestedClass the class to generate a name for; never {@code null} * @return the display name for the nested class; never blank */ String generateDisplayNameForNestedClass(Class nestedClass); /** * Generate a display name for the given method. * *

If it returns {@code null}, the default display name generator will be used instead. * * @implNote The class instance supplied as {@code testClass} may differ from * the class returned by {@code testMethod.getDeclaringClass()} — for * example, when a test method is inherited from a superclass. * * @param testClass the class the test method is invoked on; never {@code null} * @param testMethod method to generate a display name for; never {@code null} * @return the display name for the test; never blank */ String generateDisplayNameForMethod(Class testClass, Method testMethod); /** * Generate a string representation of the formal parameters of the supplied * method, consisting of the {@linkplain Class#getSimpleName() simple names} * of the parameter types, separated by commas, and enclosed in parentheses. * * @param method the method from to extract the parameter types from; never * {@code null} * @return a string representation of all parameter types of the supplied * method or {@code "()"} if the method declares no parameters */ static String parameterTypesAsString(Method method) { Preconditions.notNull(method, "Method must not be null"); return '(' + ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes()) + ')'; } /** * Standard {@code DisplayNameGenerator}. * *

This implementation matches the standard display name generation * behavior in place since JUnit Jupiter 5.0 was released. */ class Standard implements DisplayNameGenerator { static final DisplayNameGenerator INSTANCE = new Standard(); public Standard() { } @Override public String generateDisplayNameForClass(Class testClass) { String name = testClass.getName(); int lastDot = name.lastIndexOf('.'); return name.substring(lastDot + 1); } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return nestedClass.getSimpleName(); } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return testMethod.getName() + parameterTypesAsString(testMethod); } } /** * Simple {@code DisplayNameGenerator} that removes trailing parentheses * for methods with no parameters. * *

This generator extends the functionality of {@link Standard} by * removing parentheses ({@code '()'}) found at the end of method names * with no parameters. */ class Simple extends Standard { static final DisplayNameGenerator INSTANCE = new Simple(); public Simple() { } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { String displayName = testMethod.getName(); if (hasParameters(testMethod)) { displayName += ' ' + parameterTypesAsString(testMethod); } return displayName; } private static boolean hasParameters(Method method) { return method.getParameterCount() > 0; } } /** * {@code DisplayNameGenerator} that replaces underscores with spaces. * *

This generator extends the functionality of {@link Simple} by * replacing all underscores ({@code '_'}) found in class and method names * with spaces ({@code ' '}). */ class ReplaceUnderscores extends Simple { static final DisplayNameGenerator INSTANCE = new ReplaceUnderscores(); public ReplaceUnderscores() { } @Override public String generateDisplayNameForClass(Class testClass) { return replaceUnderscores(super.generateDisplayNameForClass(testClass)); } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return replaceUnderscores(super.generateDisplayNameForNestedClass(nestedClass)); } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return replaceUnderscores(super.generateDisplayNameForMethod(testClass, testMethod)); } private static String replaceUnderscores(String name) { return name.replace('_', ' '); } } /** * {@code DisplayNameGenerator} that generates complete sentences. * *

This generator generates display names that build up complete sentences * by concatenating the names of the test and the enclosing classes. The * sentence fragments are concatenated using a separator. The separator and * the display name generator for individual sentence fragments can be configured * via the {@link IndicativeSentencesGeneration @IndicativeSentencesGeneration} * annotation. * * @since 5.7 */ @API(status = STABLE, since = "5.10") class IndicativeSentences implements DisplayNameGenerator { static final DisplayNameGenerator INSTANCE = new IndicativeSentences(); public IndicativeSentences() { } @Override public String generateDisplayNameForClass(Class testClass) { return getGeneratorFor(testClass).generateDisplayNameForClass(testClass); } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return getSentenceBeginning(nestedClass); } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return getSentenceBeginning(testClass) + getFragmentSeparator(testClass) + getGeneratorFor(testClass).generateDisplayNameForMethod(testClass, testMethod); } private String getSentenceBeginning(Class testClass) { Class enclosingClass = testClass.getEnclosingClass(); boolean topLevelTestClass = (enclosingClass == null || isStatic(testClass)); Optional displayName = findAnnotation(testClass, DisplayName.class)// .map(DisplayName::value).map(String::trim); if (topLevelTestClass) { if (displayName.isPresent()) { return displayName.get(); } Class generatorClass = findDisplayNameGeneration(testClass)// .map(DisplayNameGeneration::value)// .filter(not(IndicativeSentences.class))// .orElse(null); if (generatorClass != null) { return getDisplayNameGenerator(generatorClass).generateDisplayNameForClass(testClass); } return generateDisplayNameForClass(testClass); } // Only build prefix based on the enclosing class if the enclosing // class is also configured to use the IndicativeSentences generator. boolean buildPrefix = findDisplayNameGeneration(enclosingClass)// .map(DisplayNameGeneration::value)// .filter(IndicativeSentences.class::equals)// .isPresent(); String prefix = (buildPrefix ? getSentenceBeginning(enclosingClass) + getFragmentSeparator(testClass) : ""); return prefix + displayName.orElseGet( () -> getGeneratorFor(testClass).generateDisplayNameForNestedClass(testClass)); } /** * Get the sentence fragment separator. * *

If {@link IndicativeSentencesGeneration @IndicativeSentencesGeneration} * is present (searching enclosing classes if not found locally), the * configured {@link IndicativeSentencesGeneration#separator() separator} * will be used. Otherwise, {@link IndicativeSentencesGeneration#DEFAULT_SEPARATOR} * will be used. * * @param testClass the test class to search on for {@code @IndicativeSentencesGeneration} * @return the sentence fragment separator */ private static String getFragmentSeparator(Class testClass) { return findIndicativeSentencesGeneration(testClass)// .map(IndicativeSentencesGeneration::separator)// .orElse(IndicativeSentencesGeneration.DEFAULT_SEPARATOR); } /** * Get the display name generator to use for the supplied test class. * *

If {@link IndicativeSentencesGeneration @IndicativeSentencesGeneration} * is present (searching enclosing classes if not found locally), the * configured {@link IndicativeSentencesGeneration#generator() generator} * will be used. Otherwise, {@link IndicativeSentencesGeneration#DEFAULT_GENERATOR} * will be used. * * @param testClass the test class to search on for {@code @IndicativeSentencesGeneration} * @return the {@code DisplayNameGenerator} instance to use */ private static DisplayNameGenerator getGeneratorFor(Class testClass) { return findIndicativeSentencesGeneration(testClass)// .map(IndicativeSentencesGeneration::generator)// .filter(not(IndicativeSentences.class))// .map(DisplayNameGenerator::getDisplayNameGenerator)// .orElseGet(() -> getDisplayNameGenerator(IndicativeSentencesGeneration.DEFAULT_GENERATOR)); } /** * Find the first {@code DisplayNameGeneration} annotation that is either * directly present, meta-present, or indirectly present * on the supplied {@code testClass} or on an enclosing class. * * @param testClass the test class on which to find the annotation; never {@code null} * @return an {@code Optional} containing the annotation, potentially empty if not found */ private static Optional findDisplayNameGeneration(Class testClass) { return findAnnotation(testClass, DisplayNameGeneration.class, true); } /** * Find the first {@code IndicativeSentencesGeneration} annotation that is either * directly present, meta-present, or indirectly present * on the supplied {@code testClass} or on an enclosing class. * * @param testClass the test class on which to find the annotation; never {@code null} * @return an {@code Optional} containing the annotation, potentially empty if not found */ private static Optional findIndicativeSentencesGeneration(Class testClass) { return findAnnotation(testClass, IndicativeSentencesGeneration.class, true); } private static Predicate> not(Class clazz) { return ((Predicate>) clazz::equals).negate(); } } /** * Return the {@code DisplayNameGenerator} instance corresponding to the * given {@code Class}. * * @param generatorClass the generator's {@code Class}; never {@code null}, * has to be a {@code DisplayNameGenerator} implementation * @return a {@code DisplayNameGenerator} implementation instance */ static DisplayNameGenerator getDisplayNameGenerator(Class generatorClass) { Preconditions.notNull(generatorClass, "Class must not be null"); Preconditions.condition(DisplayNameGenerator.class.isAssignableFrom(generatorClass), "Class must be a DisplayNameGenerator implementation"); if (generatorClass == Standard.class) { return Standard.INSTANCE; } if (generatorClass == Simple.class) { return Simple.INSTANCE; } if (generatorClass == ReplaceUnderscores.class) { return ReplaceUnderscores.INSTANCE; } if (generatorClass == IndicativeSentences.class) { return IndicativeSentences.INSTANCE; } return (DisplayNameGenerator) ReflectionUtils.newInstance(generatorClass); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicContainer.java000066400000000000000000000074501455764576500315160ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.net.URI; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; /** * A {@code DynamicContainer} is a container generated at runtime. * *

It is composed of a {@linkplain DynamicNode#getDisplayName display name} * and an {@link Iterable} or {@link Stream} of {@link DynamicNode DynamicNodes}. * *

Instances of {@code DynamicContainer} must be generated by factory methods * annotated with {@link TestFactory @TestFactory}. * * @since 5.0 * @see #dynamicContainer(String, Iterable) * @see #dynamicContainer(String, Stream) * @see TestFactory * @see DynamicTest */ @API(status = MAINTAINED, since = "5.3") public class DynamicContainer extends DynamicNode { /** * Factory for creating a new {@code DynamicContainer} for the supplied display * name and collection of dynamic nodes. * *

The collection of dynamic nodes must not contain {@code null} elements. * * @param displayName the display name for the dynamic container; never * {@code null} or blank * @param dynamicNodes collection of dynamic nodes to execute; * never {@code null} * @see #dynamicContainer(String, Stream) */ public static DynamicContainer dynamicContainer(String displayName, Iterable dynamicNodes) { return dynamicContainer(displayName, null, StreamSupport.stream(dynamicNodes.spliterator(), false)); } /** * Factory for creating a new {@code DynamicContainer} for the supplied display * name and stream of dynamic nodes. * *

The stream of dynamic nodes must not contain {@code null} elements. * * @param displayName the display name for the dynamic container; never * {@code null} or blank * @param dynamicNodes stream of dynamic nodes to execute; * never {@code null} * @see #dynamicContainer(String, Iterable) */ public static DynamicContainer dynamicContainer(String displayName, Stream dynamicNodes) { return dynamicContainer(displayName, null, dynamicNodes); } /** * Factory for creating a new {@code DynamicContainer} for the supplied display * name, custom test source {@link URI}, and stream of dynamic nodes. * *

The stream of dynamic nodes must not contain {@code null} elements. * * @param displayName the display name for the dynamic container; never * {@code null} or blank * @param testSourceUri a custom test source URI for the dynamic container; * may be {@code null} if the framework should generate the test source based * on the {@code @TestFactory} method * @param dynamicNodes stream of dynamic nodes to execute; never {@code null} * @since 5.3 * @see #dynamicContainer(String, Iterable) */ public static DynamicContainer dynamicContainer(String displayName, URI testSourceUri, Stream dynamicNodes) { return new DynamicContainer(displayName, testSourceUri, dynamicNodes); } private final Stream children; private DynamicContainer(String displayName, URI testSourceUri, Stream children) { super(displayName, testSourceUri); Preconditions.notNull(children, "children must not be null"); this.children = children; } /** * Get the {@link Stream} of {@link DynamicNode DynamicNodes} associated * with this {@code DynamicContainer}. */ public Stream getChildren() { return children; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java000066400000000000000000000035351455764576500304610ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.net.URI; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code DynamicNode} serves as the abstract base class for a container or a * test case generated at runtime. * * @since 5.0 * @see DynamicTest * @see DynamicContainer */ @API(status = MAINTAINED, since = "5.3") public abstract class DynamicNode { private final String displayName; /** Custom test source {@link URI} associated with this node; potentially {@code null}. */ private final URI testSourceUri; DynamicNode(String displayName, URI testSourceUri) { this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or blank"); this.testSourceUri = testSourceUri; } /** * Get the display name of this {@code DynamicNode}. * * @return the display name */ public String getDisplayName() { return this.displayName; } /** * Get the custom test source {@link URI} of this {@code DynamicNode}. * * @return an {@code Optional} containing the custom test source {@link URI}; * never {@code null} but potentially empty * @since 5.3 */ public Optional getTestSourceUri() { return Optional.ofNullable(testSourceUri); } @Override public String toString() { return new ToStringBuilder(this) // .append("displayName", displayName) // .append("testSourceUri", testSourceUri) // .toString(); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicTest.java000066400000000000000000000236221455764576500305120ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.Spliterator.ORDERED; import static java.util.Spliterators.spliteratorUnknownSize; import static org.apiguardian.api.API.Status.MAINTAINED; import java.net.URI; import java.util.Iterator; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apiguardian.api.API; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.platform.commons.util.Preconditions; /** * A {@code DynamicTest} is a test case generated at runtime. * *

It is composed of a {@linkplain DynamicNode#getDisplayName display name} * and an {@link #getExecutable Executable}. * *

Instances of {@code DynamicTest} must be generated by factory methods * annotated with {@link TestFactory @TestFactory}. * *

Note that dynamic tests are quite different from standard {@link Test @Test} * cases since callbacks such as {@link BeforeEach @BeforeEach} and * {@link AfterEach @AfterEach} methods are not executed for dynamic tests. * * @since 5.0 * @see #dynamicTest(String, Executable) * @see #stream(Iterator, Function, ThrowingConsumer) * @see Test * @see TestFactory * @see DynamicContainer * @see Executable */ @API(status = MAINTAINED, since = "5.3") public class DynamicTest extends DynamicNode { /** * Factory for creating a new {@code DynamicTest} for the supplied display * name and executable code block. * * @param displayName the display name for the dynamic test; never * {@code null} or blank * @param executable the executable code block for the dynamic test; * never {@code null} * @see #stream(Iterator, Function, ThrowingConsumer) */ public static DynamicTest dynamicTest(String displayName, Executable executable) { return new DynamicTest(displayName, null, executable); } /** * Factory for creating a new {@code DynamicTest} for the supplied display * name, custom test source {@link URI}, and executable code block. * * @param displayName the display name for the dynamic test; never * {@code null} or blank * @param testSourceUri a custom test source URI for the dynamic test; may * be {@code null} if the framework should generate the test source based on * the {@code @TestFactory} method * @param executable the executable code block for the dynamic test; * never {@code null} * @since 5.3 * @see #stream(Iterator, Function, ThrowingConsumer) */ public static DynamicTest dynamicTest(String displayName, URI testSourceUri, Executable executable) { return new DynamicTest(displayName, testSourceUri, executable); } /** * Generate a stream of dynamic tests based on the given generator and test * executor. * *

Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Iterator}. See * {@link #stream(Stream, Function, ThrowingConsumer)} as an alternative. * *

The given {@code inputGenerator} is responsible for generating * input values. A {@link DynamicTest} will be added to the resulting * stream for each dynamically generated input value, using the given * {@code displayNameGenerator} and {@code testExecutor}. * * @param inputGenerator an {@code Iterator} that serves as a dynamic * input generator; never {@code null} * @param displayNameGenerator a function that generates a display name * based on an input value; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param the type of input generated by the {@code inputGenerator} * and used by the {@code displayNameGenerator} and {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @see #dynamicTest(String, Executable) * @see #stream(Stream, Function, ThrowingConsumer) */ public static Stream stream(Iterator inputGenerator, Function displayNameGenerator, ThrowingConsumer testExecutor) { Preconditions.notNull(inputGenerator, "inputGenerator must not be null"); return stream(StreamSupport.stream(spliteratorUnknownSize(inputGenerator, ORDERED), false), displayNameGenerator, testExecutor); } /** * Generate a stream of dynamic tests based on the given input stream and * test executor. * *

Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Stream}. See * {@link #stream(Iterator, Function, ThrowingConsumer)} as an alternative. * *

The given {@code inputStream} is responsible for supplying input values. * A {@link DynamicTest} will be added to the resulting stream for each * dynamically supplied input value, using the given {@code displayNameGenerator} * and {@code testExecutor}. * * @param inputStream a {@code Stream} that supplies dynamic input values; * never {@code null} * @param displayNameGenerator a function that generates a display name * based on an input value; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param the type of input supplied by the {@code inputStream} * and used by the {@code displayNameGenerator} and {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @since 5.7 * @see #dynamicTest(String, Executable) * @see #stream(Iterator, Function, ThrowingConsumer) */ @API(status = MAINTAINED, since = "5.7") public static Stream stream(Stream inputStream, Function displayNameGenerator, ThrowingConsumer testExecutor) { Preconditions.notNull(inputStream, "inputStream must not be null"); Preconditions.notNull(displayNameGenerator, "displayNameGenerator must not be null"); Preconditions.notNull(testExecutor, "testExecutor must not be null"); return inputStream // .map(input -> dynamicTest(displayNameGenerator.apply(input), () -> testExecutor.accept(input))); } /** * Generate a stream of dynamic tests based on the given generator and test * executor. * *

Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Iterator}. See * {@link #stream(Stream, ThrowingConsumer)} as an alternative. * *

The given {@code inputGenerator} is responsible for generating * input values and display names. A {@link DynamicTest} will be added to * the resulting stream for each dynamically generated input value, * using the given {@code testExecutor}. * * @param inputGenerator an {@code Iterator} with {@code Named} values * that serves as a dynamic input generator; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param the type of input generated by the {@code inputGenerator} * and used by the {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @since 5.8 * * @see #dynamicTest(String, Executable) * @see #stream(Stream, ThrowingConsumer) * @see Named */ @API(status = MAINTAINED, since = "5.8") public static Stream stream(Iterator> inputGenerator, ThrowingConsumer testExecutor) { Preconditions.notNull(inputGenerator, "inputGenerator must not be null"); return stream(StreamSupport.stream(spliteratorUnknownSize(inputGenerator, ORDERED), false), testExecutor); } /** * Generate a stream of dynamic tests based on the given input stream and * test executor. * *

Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Stream}. See * {@link #stream(Iterator, ThrowingConsumer)} as an alternative. * *

The given {@code inputStream} is responsible for supplying input values * and display names. A {@link DynamicTest} will be added to the resulting stream for * each dynamically supplied input value, using the given {@code testExecutor}. * * @param inputStream a {@code Stream} that supplies dynamic {@code Named} * input values; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param the type of input supplied by the {@code inputStream} * and used by the {@code displayNameGenerator} and {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @since 5.8 * * @see #dynamicTest(String, Executable) * @see #stream(Iterator, ThrowingConsumer) * @see Named */ @API(status = MAINTAINED, since = "5.8") public static Stream stream(Stream> inputStream, ThrowingConsumer testExecutor) { Preconditions.notNull(inputStream, "inputStream must not be null"); Preconditions.notNull(testExecutor, "testExecutor must not be null"); return inputStream // .map(input -> dynamicTest(input.getName(), () -> testExecutor.accept(input.getPayload()))); } private final Executable executable; private DynamicTest(String displayName, URI testSourceUri, Executable executable) { super(displayName, testSourceUri); this.executable = Preconditions.notNull(executable, "executable must not be null"); } /** * Get the {@code executable} code block associated with this {@code DynamicTest}. */ public Executable getExecutable() { return this.executable; } } IndicativeSentencesGeneration.java000066400000000000000000000045321455764576500341510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.DisplayNameGenerator.IndicativeSentences; /** * {@code @IndicativeSentencesGeneration} is used to register the * {@link IndicativeSentences} display name generator and configure it. * *

The {@link #separator} for sentence fragments and the display name * {@link #generator} for sentence fragments are configurable. If this annotation * is declared without any attributes — for example, * {@code @IndicativeSentencesGeneration} or {@code @IndicativeSentencesGeneration()} * — the default configuration will be used. * *

This annotation is inherited from superclasses and implemented * interfaces. It is also inherited from {@linkplain Class#getEnclosingClass() * enclosing classes} for {@link Nested @Nested} test classes. * * @since 5.7 * @see DisplayName * @see DisplayNameGenerator * @see DisplayNameGenerator.IndicativeSentences * @see DisplayNameGeneration */ @DisplayNameGeneration(IndicativeSentences.class) @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.10") public @interface IndicativeSentencesGeneration { String DEFAULT_SEPARATOR = ", "; Class DEFAULT_GENERATOR = DisplayNameGenerator.Standard.class; /** * Custom separator for sentence fragments. * *

Defaults to {@value #DEFAULT_SEPARATOR}. */ String separator() default DEFAULT_SEPARATOR; /** * Custom display name generator to use for sentence fragments. * *

Defaults to {@link DisplayNameGenerator.Standard}. */ Class generator() default DisplayNameGenerator.Standard.class; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodDescriptor.java000066400000000000000000000053741455764576500315510ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code MethodDescriptor} encapsulates functionality for a given {@link Method}. * * @since 5.4 * @see MethodOrdererContext */ @API(status = STABLE, since = "5.7") public interface MethodDescriptor { /** * Get the method for this descriptor. * * @return the method; never {@code null} */ Method getMethod(); /** * Get the display name for this descriptor's {@link #getMethod() method}. * * @return the display name for this descriptor's method; never {@code null} * or blank * @since 5.7 */ @API(status = STABLE, since = "5.10") String getDisplayName(); /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the {@link Method} for * this descriptor. * * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @see #findAnnotation(Class) * @see #findRepeatableAnnotations(Class) */ boolean isAnnotated(Class annotationType); /** * Find the first annotation of {@code annotationType} that is either * present or meta-present on the {@link Method} for * this descriptor. * * @param the annotation type * @param annotationType the annotation type to search for; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @see #isAnnotated(Class) * @see #findRepeatableAnnotations(Class) */ Optional findAnnotation(Class annotationType); /** * Find all repeatable {@linkplain Annotation annotations} of * {@code annotationType} that are either present or * meta-present on the {@link Method} for this descriptor. * * @param the annotation type * @param annotationType the repeatable annotation type to search for; never * {@code null} * @return the list of all such annotations found; neither {@code null} nor * mutable, but potentially empty * @see #isAnnotated(Class) * @see #findAnnotation(Class) * @see java.lang.annotation.Repeatable */ List findRepeatableAnnotations(Class annotationType); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrderer.java000066400000000000000000000264011455764576500310270ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.Comparator.comparingInt; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; import java.util.Collections; import java.util.Comparator; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassUtils; /** * {@code MethodOrderer} defines the API for ordering the test methods * in a given test class. * *

In this context, the term "test method" refers to any method annotated with * {@code @Test}, {@code @RepeatedTest}, {@code @ParameterizedTest}, * {@code @TestFactory}, or {@code @TestTemplate}. * *

A {@link MethodOrderer} can be configured globally for the entire * test suite via the {@value #DEFAULT_ORDER_PROPERTY_NAME} configuration * parameter (see the User Guide for details) or locally for a test * class via the {@link TestMethodOrder @TestMethodOrder} annotation. * *

Built-in Implementations

* *

JUnit Jupiter provides the following built-in {@code MethodOrderer} * implementations. * *

    *
  • {@link MethodName}
  • *
  • {@link OrderAnnotation}
  • *
  • {@link Random}
  • *
* * @since 5.4 * @see TestMethodOrder * @see MethodOrdererContext * @see #orderMethods(MethodOrdererContext) * @see ClassOrderer */ @API(status = STABLE, since = "5.7") public interface MethodOrderer { /** * Property name used to set the default method orderer class name: {@value} * *

Supported Values

* *

Supported values include fully qualified class names for types that * implement {@link org.junit.jupiter.api.MethodOrderer}. * *

If not specified, test methods will be ordered using an algorithm that * is deterministic but intentionally non-obvious. * * @since 5.7 */ @API(status = STABLE, since = "5.9") String DEFAULT_ORDER_PROPERTY_NAME = "junit.jupiter.testmethod.order.default"; /** * Order the methods encapsulated in the supplied {@link MethodOrdererContext}. * *

The methods to order or sort are made indirectly available via * {@link MethodOrdererContext#getMethodDescriptors()}. Since this method * has a {@code void} return type, the list of method descriptors must be * modified directly. * *

For example, a simplified implementation of the {@link Random} * {@code MethodOrderer} might look like the following. * *

	 * public void orderMethods(MethodOrdererContext context) {
	 *     Collections.shuffle(context.getMethodDescriptors());
	 * }
	 * 
* * @param context the {@code MethodOrdererContext} containing the * {@linkplain MethodDescriptor method descriptors} to order; never {@code null} * @see #getDefaultExecutionMode() */ void orderMethods(MethodOrdererContext context); /** * Get the default {@link ExecutionMode} for the test class * configured with this {@link MethodOrderer}. * *

This method is guaranteed to be invoked after * {@link #orderMethods(MethodOrdererContext)} which allows implementations * of this method to determine the appropriate return value programmatically, * potentially based on actions that were taken in {@code orderMethods()}. * *

Defaults to {@link ExecutionMode#SAME_THREAD SAME_THREAD}, since * ordered methods are typically sorted in a fashion that would conflict * with concurrent execution. * *

In case the ordering does not conflict with concurrent execution, * implementations should return an empty {@link Optional} to signal that * the engine should decide which execution mode to use. * *

Can be overridden via an explicit * {@link org.junit.jupiter.api.parallel.Execution @Execution} declaration * on the test class or in concrete implementations of the * {@code MethodOrderer} API. * * @return the default {@code ExecutionMode}; never {@code null} but * potentially empty * @see #orderMethods(MethodOrdererContext) */ default Optional getDefaultExecutionMode() { return Optional.of(ExecutionMode.SAME_THREAD); } /** * {@code MethodOrderer} that sorts methods alphanumerically based on their * names using {@link String#compareTo(String)}. * *

If two methods have the same name, {@code String} representations of * their formal parameter lists will be used as a fallback for comparing the * methods. * * @since 5.4 * @deprecated as of JUnit Jupiter 5.7 in favor of {@link MethodOrderer.MethodName}; * to be removed in 6.0 */ @API(status = DEPRECATED, since = "5.7") @Deprecated class Alphanumeric extends MethodName { public Alphanumeric() { } } /** * {@code MethodOrderer} that sorts methods alphanumerically based on their * names using {@link String#compareTo(String)}. * *

If two methods have the same name, {@code String} representations of * their formal parameter lists will be used as a fallback for comparing the * methods. * * @since 5.7 */ @API(status = STABLE, since = "5.10") class MethodName implements MethodOrderer { public MethodName() { } /** * Sort the methods encapsulated in the supplied * {@link MethodOrdererContext} alphanumerically based on their names * and formal parameter lists. */ @Override public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().sort(comparator); } private static final Comparator comparator = Comparator. // comparing(descriptor -> descriptor.getMethod().getName())// .thenComparing(descriptor -> parameterList(descriptor.getMethod())); private static String parameterList(Method method) { return ClassUtils.nullSafeToString(method.getParameterTypes()); } } /** * {@code MethodOrderer} that sorts methods alphanumerically based on their * display names using {@link String#compareTo(String)} * * @since 5.7 */ @API(status = STABLE, since = "5.10") class DisplayName implements MethodOrderer { public DisplayName() { } /** * Sort the methods encapsulated in the supplied * {@link MethodOrdererContext} alphanumerically based on their display * names. */ @Override public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().sort(comparator); } private static final Comparator comparator = Comparator.comparing( MethodDescriptor::getDisplayName); } /** * {@code MethodOrderer} that sorts methods based on the {@link Order @Order} * annotation. * *

Any methods that are assigned the same order value will be sorted * arbitrarily adjacent to each other. * *

Any methods not annotated with {@code @Order} will be assigned the * {@linkplain Order#DEFAULT default order} value which will effectively cause them * to appear at the end of the sorted list, unless certain methods are assigned * an explicit order value greater than the default order value. Any methods * assigned an explicit order value greater than the default order value will * appear after non-annotated methods in the sorted list. */ class OrderAnnotation implements MethodOrderer { public OrderAnnotation() { } /** * Sort the methods encapsulated in the supplied * {@link MethodOrdererContext} based on the {@link Order @Order} * annotation. */ @Override public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().sort(comparingInt(OrderAnnotation::getOrder)); } private static int getOrder(MethodDescriptor descriptor) { return descriptor.findAnnotation(Order.class).map(Order::value).orElse(Order.DEFAULT); } } /** * {@code MethodOrderer} that orders methods pseudo-randomly. * *

Custom Seed

* *

By default, the random seed used for ordering methods is the * value returned by {@link System#nanoTime()} during static initialization * of this class. In order to support repeatable builds, the value of the * default random seed is logged at {@code CONFIG} level. In addition, a * custom seed (potentially the default seed from the previous test plan * execution) may be specified via the {@value ClassOrderer.Random#RANDOM_SEED_PROPERTY_NAME} * configuration parameter which can be supplied via the {@code Launcher} * API, build tools (e.g., Gradle and Maven), a JVM system property, or the JUnit * Platform configuration file (i.e., a file named {@code junit-platform.properties} * in the root of the class path). Consult the User Guide for further information. * * @see Random#RANDOM_SEED_PROPERTY_NAME * @see java.util.Random */ class Random implements MethodOrderer { private static final Logger logger = LoggerFactory.getLogger(Random.class); /** * Default seed, which is generated during initialization of this class * via {@link System#nanoTime()} for reproducibility of tests. */ private static final long DEFAULT_SEED; static { DEFAULT_SEED = System.nanoTime(); logger.config(() -> "MethodOrderer.Random default seed: " + DEFAULT_SEED); } /** * Property name used to set the random seed used by this * {@code MethodOrderer}: {@value} * *

The same property is used by {@link ClassOrderer.Random} for * consistency between the two random orderers. * *

Supported Values

* *

Supported values include any string that can be converted to a * {@link Long} via {@link Long#valueOf(String)}. * *

If not specified or if the specified value cannot be converted to * a {@link Long}, the default random seed will be used (see the * {@linkplain Random class-level Javadoc} for details). * * @see ClassOrderer.Random */ public static final String RANDOM_SEED_PROPERTY_NAME = "junit.jupiter.execution.order.random.seed"; public Random() { } /** * Order the methods encapsulated in the supplied * {@link MethodOrdererContext} pseudo-randomly. */ @Override public void orderMethods(MethodOrdererContext context) { Collections.shuffle(context.getMethodDescriptors(), new java.util.Random(getCustomSeed(context).orElse(DEFAULT_SEED))); } private Optional getCustomSeed(MethodOrdererContext context) { return context.getConfigurationParameter(RANDOM_SEED_PROPERTY_NAME).map(configurationParameter -> { Long seed = null; try { seed = Long.valueOf(configurationParameter); logger.config( () -> String.format("Using custom seed for configuration parameter [%s] with value [%s].", RANDOM_SEED_PROPERTY_NAME, configurationParameter)); } catch (NumberFormatException ex) { logger.warn(ex, () -> String.format( "Failed to convert configuration parameter [%s] with value [%s] to a long. " + "Using default seed [%s] as fallback.", RANDOM_SEED_PROPERTY_NAME, configurationParameter, DEFAULT_SEED)); } return seed; }); } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrdererContext.java000066400000000000000000000034271455764576500323770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code MethodOrdererContext} encapsulates the context in which * a {@link MethodOrderer} will be invoked. * * @since 5.4 * @see MethodOrderer * @see MethodDescriptor */ @API(status = STABLE, since = "5.7") public interface MethodOrdererContext { /** * Get the test class for this context. * * @return the test class; never {@code null} */ Class getTestClass(); /** * Get the list of {@linkplain MethodDescriptor method descriptors} to * order. * * @return the list of method descriptors; never {@code null} */ List getMethodDescriptors(); /** * Get the configuration parameter stored under the specified {@code key}. * *

If no such key is present in the {@code ConfigurationParameters} for * the JUnit Platform, an attempt will be made to look up the value as a * JVM system property. If no such system property exists, an attempt will * be made to look up the value in the JUnit Platform properties file. * * @param key the key to look up; never {@code null} or blank * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @see System#getProperty(String) * @see org.junit.platform.engine.ConfigurationParameters */ Optional getConfigurationParameter(String key); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Named.java000066400000000000000000000046561455764576500273200ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; /** * {@code Named} is a container that associates a name with a given payload. * * @param the type of the payload * * @since 5.8 */ @API(status = STABLE, since = "5.8") public interface Named { /** * Factory method for creating an instance of {@code Named} based on a * {@code name} and a {@code payload}. * * @param name the name associated with the payload; never {@code null} or * blank * @param payload the object that serves as the payload; may be {@code null} * depending on the use case * @param the type of the payload * @return an instance of {@code Named}; never {@code null} * @see #named(String, java.lang.Object) */ static Named of(String name, T payload) { Preconditions.notBlank(name, "name must not be null or blank"); return new Named() { @Override public String getName() { return name; } @Override public T getPayload() { return payload; } @Override public String toString() { return name; } }; } /** * Factory method for creating an instance of {@code Named} based on a * {@code name} and a {@code payload}. * *

This method is an alias for {@link Named#of} and is * intended to be used when statically imported — for example, via: * {@code import static org.junit.jupiter.api.Named.named;} * * @param name the name associated with the payload; never {@code null} or * blank * @param payload the object that serves as the payload; may be {@code null} * depending on the use case * @param the type of the payload * @return an instance of {@code Named}; never {@code null} */ static Named named(String name, T payload) { return of(name, payload); } /** * Get the name of the payload. * * @return the name of the payload; never {@code null} or blank */ String getName(); /** * Get the payload. * * @return the payload; may be {@code null} depending on the use case */ T getPayload(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Nested.java000066400000000000000000000033501455764576500275040ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance.Lifecycle; /** * {@code @Nested} is used to signal that the annotated class is a nested, * non-static test class (i.e., an inner class) that can share * setup and state with an instance of its {@linkplain Class#getEnclosingClass() * enclosing class}. The enclosing class may be a top-level test class or * another {@code @Nested} test class, and nesting can be arbitrarily deep. * *

{@code @Nested} test classes may be ordered via * {@link TestClassOrder @TestClassOrder} or a global {@link ClassOrderer}. * *

Test Instance Lifecycle

* *
    *
  • A {@code @Nested} test class can be configured with its own * {@link Lifecycle} mode which may differ from that of an enclosing test * class.
  • *
  • A {@code @Nested} test class cannot change the {@link Lifecycle} * mode of an enclosing test class.
  • *
* * @since 5.0 * @see Test * @see TestInstance * @see TestClassOrder */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") public @interface Nested { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Order.java000066400000000000000000000045621455764576500273430ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Order} is an annotation that is used to configure the * {@linkplain #value order} in which the annotated element (i.e., field, * method, or class) should be evaluated or executed relative to other elements * of the same category. * *

When used with * {@link org.junit.jupiter.api.extension.RegisterExtension @RegisterExtension} or * {@link org.junit.jupiter.api.extension.ExtendWith @ExtendWith}, * the category applies to extension fields. When used with * {@link MethodOrderer.OrderAnnotation}, the category applies to test methods. * When used with {@link ClassOrderer.OrderAnnotation}, the category applies to * test classes. * *

If {@code @Order} is not explicitly declared on an element, the * {@link #DEFAULT} order value will be assigned to the element. * * @since 5.4 * @see MethodOrderer.OrderAnnotation * @see ClassOrderer.OrderAnnotation * @see org.junit.jupiter.api.extension.RegisterExtension @RegisterExtension * @see org.junit.jupiter.api.extension.ExtendWith @ExtendWith */ @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.9") public @interface Order { /** * Default order value for elements not explicitly annotated with {@code @Order}, * equal to the value of {@code Integer.MAX_VALUE / 2}. * * @since 5.6 * @see Order#value */ int DEFAULT = Integer.MAX_VALUE / 2; /** * The order value for the annotated element (i.e., field, method, or class). * *

Elements are ordered based on priority where a lower value has greater * priority than a higher value. For example, {@link Integer#MAX_VALUE} has * the lowest priority. * * @see #DEFAULT */ int value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepeatedTest.java000066400000000000000000000162701455764576500306600ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @RepeatedTest} is used to signal that the annotated method is a * test template method that should be repeated a {@linkplain #value * specified number of times} with a configurable {@linkplain #name display * name} and an optional {@linkplain #failureThreshold() failure threshold}. * *

Each invocation of the repeated test behaves like the execution of a * regular {@link Test @Test} method with full support for the same lifecycle * callbacks and extensions. In addition, the current repetition and total * number of repetitions can be accessed by having the {@link RepetitionInfo} * injected. * *

{@code @RepeatedTest} methods must not be {@code private} or {@code static} * and must return {@code void}. * *

{@code @RepeatedTest} methods may optionally declare parameters to be * resolved by {@link org.junit.jupiter.api.extension.ParameterResolver * ParameterResolvers}. * *

{@code @RepeatedTest} may also be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @RepeatedTest}. * *

Test Execution Order

* *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with {@link TestMethodOrder @TestMethodOrder} * and specify the desired {@link MethodOrderer} implementation. * * @since 5.0 * @see DisplayName * @see RepetitionInfo * @see TestTemplate * @see TestInfo * @see Test */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") @TestTemplate public @interface RepeatedTest { /** * Placeholder for the {@linkplain TestInfo#getDisplayName display name} of * a {@code @RepeatedTest} method: {displayName} */ String DISPLAY_NAME_PLACEHOLDER = "{displayName}"; /** * Placeholder for the current repetition count of a {@code @RepeatedTest} * method: {currentRepetition} */ String CURRENT_REPETITION_PLACEHOLDER = "{currentRepetition}"; /** * Placeholder for the total number of repetitions of a {@code @RepeatedTest} * method: {totalRepetitions} */ String TOTAL_REPETITIONS_PLACEHOLDER = "{totalRepetitions}"; /** * Short display name pattern for a repeated test: {@value} * * @see #CURRENT_REPETITION_PLACEHOLDER * @see #TOTAL_REPETITIONS_PLACEHOLDER * @see #LONG_DISPLAY_NAME */ String SHORT_DISPLAY_NAME = "repetition " + CURRENT_REPETITION_PLACEHOLDER + " of " + TOTAL_REPETITIONS_PLACEHOLDER; /** * Long display name pattern for a repeated test: {@value} * * @see #DISPLAY_NAME_PLACEHOLDER * @see #SHORT_DISPLAY_NAME */ String LONG_DISPLAY_NAME = DISPLAY_NAME_PLACEHOLDER + " :: " + SHORT_DISPLAY_NAME; /** * The number of repetitions. * * @return the number of repetitions; must be greater than zero */ int value(); /** * The display name for each repetition of the repeated test. * *

Supported placeholders

*
    *
  • {@link #DISPLAY_NAME_PLACEHOLDER}
  • *
  • {@link #CURRENT_REPETITION_PLACEHOLDER}
  • *
  • {@link #TOTAL_REPETITIONS_PLACEHOLDER}
  • *
* *

Defaults to {@link #SHORT_DISPLAY_NAME}, resulting in * names such as {@code "repetition 1 of 2"}, {@code "repetition 2 of 2"}, * etc. * *

Can be set to {@link #LONG_DISPLAY_NAME}, resulting in * names such as {@code "myRepeatedTest() :: repetition 1 of 2"}, * {@code "myRepeatedTest() :: repetition 2 of 2"}, etc. * *

Alternatively, you can provide a custom display name, optionally * using the aforementioned placeholders. * * @return a custom display name; never blank or consisting solely of * whitespace * @see #SHORT_DISPLAY_NAME * @see #LONG_DISPLAY_NAME * @see #DISPLAY_NAME_PLACEHOLDER * @see #CURRENT_REPETITION_PLACEHOLDER * @see #TOTAL_REPETITIONS_PLACEHOLDER * @see TestInfo#getDisplayName() */ String name() default SHORT_DISPLAY_NAME; /** * Configures the number of failures after which remaining repetitions will * be automatically skipped. * *

Set this to a positive number less than the total {@linkplain #value() * number of repetitions} in order to skip the invocations of remaining * repetitions after the specified number of failures has been encountered. * *

For example, if you are using {@code @RepeatedTest} to repeatedly invoke * a test that you suspect to be flaky, a single failure is sufficient * to demonstrate that the test is flaky, and there is no need to invoke the * remaining repetitions. To support that specific use case, set * {@code failureThreshold = 1}. You can alternatively set the threshold to * a number greater than {@code 1} depending on your use case. * *

Defaults to {@link Integer#MAX_VALUE}, signaling that no failure * threshold will be applied, which effectively means that the specified * {@linkplain #value() number of repetitions} will be invoked regardless of * whether any repetitions fail. * *

WARNING: if the repetitions of a {@code @RepeatedTest} * method are executed in parallel, no guarantees can be made regarding the * failure threshold. It is therefore recommended that a {@code @RepeatedTest} * method be annotated with * {@link org.junit.jupiter.api.parallel.Execution @Execution(SAME_THREAD)} * when parallel execution is configured. * * @since 5.10 * @return the failure threshold; must be greater than zero and less than the * total number of repetitions */ @API(status = EXPERIMENTAL, since = "5.10") int failureThreshold() default Integer.MAX_VALUE; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepetitionInfo.java000066400000000000000000000042461455764576500312250ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code RepetitionInfo} is used to inject information about the current * repetition of a repeated test into {@code @RepeatedTest}, {@code @BeforeEach}, * and {@code @AfterEach} methods. * *

If a method parameter is of type {@code RepetitionInfo}, JUnit will * supply an instance of {@code RepetitionInfo} corresponding to the current * repeated test as the value for the parameter. * *

WARNING: {@code RepetitionInfo} cannot be injected into * a {@code @BeforeEach} or {@code @AfterEach} method if the corresponding test * method is not a {@code @RepeatedTest}. Any attempt to do so will result in a * {@link org.junit.jupiter.api.extension.ParameterResolutionException * ParameterResolutionException}. * * @since 5.0 * @see RepeatedTest * @see TestInfo */ @API(status = STABLE, since = "5.0") public interface RepetitionInfo { /** * Get the current repetition of the corresponding * {@link RepeatedTest @RepeatedTest} method. */ int getCurrentRepetition(); /** * Get the total number of repetitions of the corresponding * {@link RepeatedTest @RepeatedTest} method. * * @see RepeatedTest#value */ int getTotalRepetitions(); /** * Get the current number of repetitions of the corresponding * {@link RepeatedTest @RepeatedTest} method that have ended in a failure. * * @since 5.10 * @see #getFailureThreshold() */ @API(status = EXPERIMENTAL, since = "5.10") int getFailureCount(); /** * Get the configured failure threshold of the corresponding * {@link RepeatedTest @RepeatedTest} method. * * @since 5.10 * @see RepeatedTest#failureThreshold() */ @API(status = EXPERIMENTAL, since = "5.10") int getFailureThreshold(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Tag.java000066400000000000000000000046031455764576500267770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Tag} is a {@linkplain Repeatable repeatable} annotation that is * used to declare a tag for the annotated test class or test method. * *

Tags are used to filter which tests are executed for a given test * plan. For example, a development team may tag tests with values such as * {@code "fast"}, {@code "slow"}, {@code "ci-server"}, etc. and then supply a * list of tags to be included in or excluded from the current test plan, * potentially dependent on the current environment. * *

Syntax Rules for Tags

*
    *
  • A tag must not be blank.
  • *
  • A trimmed tag must not contain whitespace.
  • *
  • A trimmed tag must not contain ISO control characters.
  • *
  • A trimmed tag must not contain any of the following * reserved characters. *
      *
    • {@code ,}: comma
    • *
    • {@code (}: left parenthesis
    • *
    • {@code )}: right parenthesis
    • *
    • {@code &}: ampersand
    • *
    • {@code |}: vertical bar
    • *
    • {@code !}: exclamation point
    • *
    *
  • *
* * @since 5.0 * @see Tags * @see Test */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Repeatable(Tags.class) @API(status = STABLE, since = "5.0") public @interface Tag { /** * The tag. * *

Note: the tag will first be {@linkplain String#trim() trimmed}. If the * supplied tag is syntactically invalid after trimming, the error will be * logged as a warning, and the invalid tag will be effectively ignored. See * {@linkplain Tag Syntax Rules for Tags}. */ String value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Tags.java000066400000000000000000000023571455764576500271660ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Tags} is a container for one or more {@link Tag @Tag} declarations. * *

Note, however, that use of the {@code @Tags} container is completely * optional since {@code @Tag} is a {@linkplain java.lang.annotation.Repeatable * repeatable} annotation. * * @since 5.0 * @see Tag * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.0") public @interface Tags { /** * An array of one or more {@link Tag Tags}. */ Tag[] value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Test.java000066400000000000000000000054611455764576500272060ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.platform.commons.annotation.Testable; /** * {@code @Test} is used to signal that the annotated method is a * test method. * *

{@code @Test} methods must not be {@code private} or {@code static} * and must not return a value. * *

{@code @Test} methods may optionally declare parameters to be * resolved by {@link org.junit.jupiter.api.extension.ParameterResolver * ParameterResolvers}. * *

{@code @Test} may also be used as a meta-annotation in order to create * a custom composed annotation that inherits the semantics of * {@code @Test}. * *

Test Execution Order

* *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with {@link TestMethodOrder @TestMethodOrder} * and specify the desired {@link MethodOrderer} implementation. * * @since 5.0 * @see RepeatedTest * @see org.junit.jupiter.params.ParameterizedTest * @see TestTemplate * @see TestFactory * @see TestInfo * @see DisplayName * @see Tag * @see BeforeAll * @see AfterAll * @see BeforeEach * @see AfterEach */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") @Testable public @interface Test { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestClassOrder.java000066400000000000000000000051111455764576500311600ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @TestClassOrder} is a type-level annotation that is used to configure * a {@link #value ClassOrderer} for the {@link Nested @Nested} test classes of * the annotated test class. * *

If {@code @TestClassOrder} is not explicitly declared on a test class, * inherited from a parent class, declared on a test interface implemented by * a test class, or inherited from an {@linkplain Class#getEnclosingClass() enclosing * class}, {@code @Nested} test classes will be executed in arbitrary order. * *

As an alternative to {@code @TestClassOrder}, a global {@link ClassOrderer} * can be configured for the entire test suite via the * {@value ClassOrderer#DEFAULT_ORDER_PROPERTY_NAME} configuration parameter. See * the User Guide for details. Note, however, that a {@code @TestClassOrder} * declaration always overrides a global {@code ClassOrderer}. * *

Example Usage

* *

The following demonstrates how to guarantee that {@code @Nested} test classes * are executed in the order specified via the {@link Order @Order} annotation. * *

 * {@literal @}TestClassOrder(ClassOrderer.OrderAnnotation.class)
 * class OrderedNestedTests {
 *
 *     {@literal @}Nested
 *     {@literal @}Order(1)
 *     class PrimaryTests {
 *         // {@literal @}Test methods ...
 *     }
 *
 *     {@literal @}Nested
 *     {@literal @}Order(2)
 *     class SecondaryTests {
 *         // {@literal @}Test methods ...
 *     }
 * }
 * 
* * @since 5.8 * @see ClassOrderer * @see TestMethodOrder */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.10") public @interface TestClassOrder { /** * The {@link ClassOrderer} to use. * * @see ClassOrderer * @see ClassOrderer.ClassName * @see ClassOrderer.DisplayName * @see ClassOrderer.OrderAnnotation * @see ClassOrderer.Random */ Class value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestFactory.java000066400000000000000000000063201455764576500305310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.platform.commons.annotation.Testable; /** * {@code @TestFactory} is used to signal that the annotated method is a * test factory method. * *

In contrast to {@link Test @Test} methods, a test factory is not itself * a test case but rather a factory for test cases. * *

{@code @TestFactory} methods must not be {@code private} or {@code static} * and must return a {@code Stream}, {@code Collection}, {@code Iterable}, * {@code Iterator}, or array of {@link DynamicNode} instances. Supported * subclasses of {@code DynamicNode} include {@link DynamicContainer} and * {@link DynamicTest}. Dynamic tests will be executed lazily, * enabling dynamic and even non-deterministic generation of test cases. * *

Any {@code Stream} returned by a {@code @TestFactory} will be properly * closed by calling {@code stream.close()}, making it safe to use a resource * such as {@code Files.lines()} as the initial source of the stream. * *

{@code @TestFactory} methods may optionally declare parameters to be * resolved by {@link org.junit.jupiter.api.extension.ParameterResolver * ParameterResolvers}. * *

Test Execution Order

* *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with {@link TestMethodOrder @TestMethodOrder} * and specify the desired {@link MethodOrderer} implementation. * * @since 5.0 * @see Test * @see DynamicNode * @see DynamicTest * @see DynamicContainer */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = MAINTAINED, since = "5.3") @Testable public @interface TestFactory { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInfo.java000066400000000000000000000071451455764576500300230ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; /** * {@code TestInfo} is used to inject information about the current test or * container into to {@code @Test}, {@code @RepeatedTest}, * {@code @ParameterizedTest}, {@code @TestFactory}, {@code @BeforeEach}, * {@code @AfterEach}, {@code @BeforeAll}, and {@code @AfterAll} methods. * *

If a method parameter is of type {@link TestInfo}, JUnit will supply * an instance of {@code TestInfo} corresponding to the current test or * container as the value for the parameter. * * @since 5.0 * @see Test * @see RepeatedTest * @see TestFactory * @see BeforeEach * @see AfterEach * @see BeforeAll * @see AfterAll * @see DisplayName * @see Tag */ @API(status = STABLE, since = "5.0") public interface TestInfo { /** * Get the display name of the current test or container. * *

The display name is either a default name or a custom name configured * via {@link DisplayName @DisplayName}. * *

Default Display Names

* *

If the context in which {@code TestInfo} is used is at the container * level, the default display name is generated based on the name of the * test class. For top-level and {@link Nested @Nested} test classes, the * default display name is the {@linkplain Class#getSimpleName simple name} * of the class. For {@code static} nested test classes, the default display * name is the default display name for the enclosing class concatenated with * the {@linkplain Class#getSimpleName simple name} of the {@code static} * nested class, separated by a dollar sign ({@code $}). For example, the * default display names for the following test classes are * {@code TopLevelTests}, {@code NestedTests}, and {@code TopLevelTests$StaticTests}. * *

	 *   class TopLevelTests {
	 *
	 *      {@literal @}Nested
	 *      class NestedTests {}
	 *
	 *      static class StaticTests {}
	 *   }
	 * 
* *

If the context in which {@code TestInfo} is used is at the test level, * the default display name is the name of the test method concatenated with * a comma-separated list of {@linkplain Class#getSimpleName simple names} * of the parameter types in parentheses. For example, the default display * name for the following test method is {@code testUser(TestInfo, User)}. * *

	 *   {@literal @}Test
	 *   void testUser(TestInfo testInfo, {@literal @}Mock User user) {}
	 * 
* *

Note that display names are typically used for test reporting in IDEs * and build tools and may contain spaces, special characters, and even emoji. * * @return the display name of the test or container; never {@code null} or blank */ String getDisplayName(); /** * Get the set of all tags for the current test or container. * *

Tags may be declared directly on the test element or inherited * from an outer context. */ Set getTags(); /** * Get the {@link Class} associated with the current test or container, if available. */ Optional> getTestClass(); /** * Get the {@link Method} associated with the current test or container, if available. */ Optional getTestMethod(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java000066400000000000000000000103621455764576500306670ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @TestInstance} is a type-level annotation that is used to configure * the {@linkplain Lifecycle lifecycle} of test instances for the annotated * test class or test interface. * *

If {@code @TestInstance} is not explicitly declared on a test class or * on a test interface implemented by a test class, the lifecycle mode will * implicitly default to {@link Lifecycle#PER_METHOD PER_METHOD}. Note, however, * that an explicit lifecycle mode is inherited within a test class * hierarchy. In addition, the default lifecycle mode may be overridden * via the {@value Lifecycle#DEFAULT_LIFECYCLE_PROPERTY_NAME} configuration * parameter which can be supplied via the {@code Launcher} API, build tools * (e.g., Gradle and Maven), a JVM system property, or the JUnit Platform * configuration file (i.e., a file named {@code junit-platform.properties} in * the root of the class path). Consult the User Guide for further information. * *

Use Cases

*

Setting the test instance lifecycle mode to {@link Lifecycle#PER_CLASS * PER_CLASS} enables the following features. *

    *
  • Shared test instance state between test methods in a given test class * as well as between non-static {@link BeforeAll @BeforeAll} and * {@link AfterAll @AfterAll} methods in the test class.
  • *
  • Declaration of non-static {@code @BeforeAll} and {@code @AfterAll} methods * in {@link Nested @Nested} test classes. Beginning with Java 16, {@code @BeforeAll} * and {@code @AfterAll} methods may be declared as {@code static} in * {@link Nested @Nested} test classes with either lifecycle mode.
  • *
  • Declaration of {@code @BeforeAll} and {@code @AfterAll} on interface * {@code default} methods.
  • *
  • Simplified declaration of non-static {@code @BeforeAll} and {@code @AfterAll} * lifecycle methods as well as {@code @MethodSource} factory methods in test classes * implemented with the Kotlin programming language.
  • *
* *

{@code @TestInstance} may also be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @TestInstance}. * * @since 5.0 * @see Nested @Nested */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @API(status = STABLE, since = "5.0") public @interface TestInstance { /** * Enumeration of test instance lifecycle modes. * * @see #PER_METHOD * @see #PER_CLASS */ enum Lifecycle { /** * When using this mode, a new test instance will be created once per * test class. * * @see #PER_METHOD */ PER_CLASS, /** * When using this mode, a new test instance will be created for each * test method, test factory method, or test template method. * *

This mode is analogous to the behavior found in JUnit versions 1 * through 4. * * @see #PER_CLASS */ PER_METHOD; /** * Property name used to set the default test instance lifecycle mode: * {@value} * *

Supported Values

* *

Supported values include names of enum constants defined in * {@link org.junit.jupiter.api.TestInstance.Lifecycle}, ignoring case. * *

If not specified, the default is "per_method" which corresponds to * {@code @TestInstance(Lifecycle.PER_METHOD)}. * * @since 5.0 * @see org.junit.jupiter.api.TestInstance */ @API(status = STABLE, since = "5.9") public static final String DEFAULT_LIFECYCLE_PROPERTY_NAME = "junit.jupiter.testinstance.lifecycle.default"; } /** * The test instance lifecycle mode to use. */ Lifecycle value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestMethodOrder.java000066400000000000000000000053321455764576500313400ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @TestMethodOrder} is a type-level annotation that is used to configure * a {@link #value MethodOrderer} for the test methods of the annotated * test class or test interface. * *

In this context, the term "test method" refers to any method annotated with * {@code @Test}, {@code @RepeatedTest}, {@code @ParameterizedTest}, * {@code @TestFactory}, or {@code @TestTemplate}. * *

If {@code @TestMethodOrder} is not explicitly declared on a test class, * inherited from a parent class, or declared on a test interface implemented by * a test class, test methods will be ordered using a default algorithm that is * deterministic but intentionally nonobvious. * *

As an alternative to {@code @TestMethodOrder}, a global {@link MethodOrderer} * can be configured for the entire test suite via the * {@value MethodOrderer#DEFAULT_ORDER_PROPERTY_NAME} configuration parameter. See * the User Guide for details. Note, however, that a {@code @TestClassOrder} * declaration always overrides a global {@code ClassOrderer}. * *

Example Usage

* *

The following demonstrates how to guarantee that test methods are executed * in the order specified via the {@link Order @Order} annotation. * *

 * {@literal @}TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 * class OrderedTests {
 *
 *     {@literal @}Test
 *     {@literal @}Order(1)
 *     void nullValues() {}
 *
 *     {@literal @}Test
 *     {@literal @}Order(2)
 *     void emptyValues() {}
 *
 *     {@literal @}Test
 *     {@literal @}Order(3)
 *     void validValues() {}
 * }
 * 
* * @since 5.4 * @see MethodOrderer * @see TestClassOrder */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.7") public @interface TestMethodOrder { /** * The {@link MethodOrderer} to use. * * @see MethodOrderer * @see MethodOrderer.MethodName * @see MethodOrderer.DisplayName * @see MethodOrderer.OrderAnnotation * @see MethodOrderer.Random */ Class value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java000066400000000000000000000047271455764576500307350ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; import java.util.Map; import org.apiguardian.api.API; /** * Parameters of type {@code TestReporter} can be injected into * {@link BeforeEach @BeforeEach} and {@link AfterEach @AfterEach} lifecycle * methods as well as methods annotated with {@link Test @Test}, * {@link RepeatedTest @RepeatedTest}, * {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest}, * {@link TestFactory @TestFactory}, etc. * *

Within such methods the injected {@code TestReporter} can be used to * publish report entries for the current container or test to the * reporting infrastructure. * * @since 5.0 * @see #publishEntry(Map) * @see #publishEntry(String, String) */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface TestReporter { /** * Publish the supplied map of key-value pairs as a report entry. * * @param map the key-value pairs to be published; never {@code null}; * keys and values within entries in the map also must not be * {@code null} or blank * @see #publishEntry(String, String) * @see #publishEntry(String) */ void publishEntry(Map map); /** * Publish the supplied key-value pair as a report entry. * * @param key the key of the entry to publish; never {@code null} or blank * @param value the value of the entry to publish; never {@code null} or blank * @see #publishEntry(Map) * @see #publishEntry(String) */ default void publishEntry(String key, String value) { this.publishEntry(Collections.singletonMap(key, value)); } /** * Publish the supplied value as a report entry. * *

This method delegates to {@link #publishEntry(String, String)}, * supplying {@code "value"} as the key and the supplied {@code value} * argument as the value. * * @param value the value to be published; never {@code null} or blank * @since 5.3 * @see #publishEntry(Map) * @see #publishEntry(String, String) */ @API(status = STABLE, since = "5.3") default void publishEntry(String value) { this.publishEntry("value", value); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestTemplate.java000066400000000000000000000067631455764576500307100ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.platform.commons.annotation.Testable; /** * {@code @TestTemplate} is used to signal that the annotated method is a * test template method. * *

In contrast to {@link Test @Test} methods, a test template is not itself * a test case but rather a template for test cases. As such, it is designed to * be invoked multiple times depending on the number of {@linkplain * org.junit.jupiter.api.extension.TestTemplateInvocationContext invocation * contexts} returned by the registered {@linkplain * org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider * providers}. Must be used together with at least one provider. Otherwise, * execution will fail. * *

Each invocation of a test template method behaves like the execution of * a regular {@link Test @Test} method with full support for the same lifecycle * callbacks and extensions. * *

{@code @TestTemplate} methods must not be {@code private} or {@code static} * and must return {@code void}. * *

{@code @TestTemplate} methods may optionally declare parameters to be * resolved by {@link org.junit.jupiter.api.extension.ParameterResolver * ParameterResolvers}. * *

{@code @TestTemplate} may also be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @TestTemplate}. * *

Test Execution Order

* *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with {@link TestMethodOrder @TestMethodOrder} * and specify the desired {@link MethodOrderer} implementation. * * @since 5.0 * @see Test * @see org.junit.jupiter.api.extension.TestTemplateInvocationContext * @see org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") @Testable public @interface TestTemplate { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Timeout.java000066400000000000000000000346771455764576500277300ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.TimeUnit; import org.apiguardian.api.API; /** * {@code @Timeout} is used to define a timeout for a method or all testable * methods within one class and its {@link Nested @Nested} classes. * *

This annotation may also be used on lifecycle methods annotated with * {@link BeforeAll @BeforeAll}, {@link BeforeEach @BeforeEach}, * {@link AfterEach @AfterEach}, or {@link AfterAll @AfterAll}. * *

Applying this annotation to a test class has the same effect as applying * it to all testable methods, i.e. all methods annotated or meta-annotated with * {@link Test @Test}, {@link TestFactory @TestFactory}, or * {@link TestTemplate @TestTemplate}, but not to its lifecycle methods. * *

Default Timeouts

* *

If this annotation is not present, no timeout will be used unless a * default timeout is defined via one of the following configuration parameters: * *

*
{@value #DEFAULT_TIMEOUT_PROPERTY_NAME}
*
Default timeout for all testable and lifecycle methods
*
{@value #DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for all testable methods
*
{@value #DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link Test @Test} methods
*
{@value #DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link TestTemplate @TestTemplate} methods
*
{@value #DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link TestFactory @TestFactory} methods
*
{@value #DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for all lifecycle methods
*
{@value #DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link BeforeAll @BeforeAll} methods
*
{@value #DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link BeforeEach @BeforeEach} methods
*
{@value #DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link AfterEach @AfterEach} methods
*
{@value #DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME}
*
Default timeout for {@link AfterAll @AfterAll} methods
*
* *

More specific configuration parameters override less specific ones. For * example, {@value #DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME} * overrides {@value #DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME} * which overrides {@value #DEFAULT_TIMEOUT_PROPERTY_NAME}. * *

Supported Values

* *

Values for timeouts must be in the following, case-insensitive format: * {@code [ns|μs|ms|s|m|h|d]}. The space between the number and the * unit may be omitted. Specifying no unit is equivalent to using seconds. * * * * * * * * * * * * *
Timeout configuration via configuration parameter vs. annotation
Value Equivalent annotation
{@code 42} {@code @Timeout(42)}
{@code 42 ns} {@code @Timeout(value = 42, unit = NANOSECONDS)}
{@code 42 μs} {@code @Timeout(value = 42, unit = MICROSECONDS)}
{@code 42 ms} {@code @Timeout(value = 42, unit = MILLISECONDS)}
{@code 42 s} {@code @Timeout(value = 42, unit = SECONDS)}
{@code 42 m} {@code @Timeout(value = 42, unit = MINUTES)}
{@code 42 h} {@code @Timeout(value = 42, unit = HOURS)}
{@code 42 d} {@code @Timeout(value = 42, unit = DAYS)}
* *

Disabling Timeouts

* *

You may use the {@value #TIMEOUT_MODE_PROPERTY_NAME} configuration * parameter to explicitly enable or disable timeouts. * *

Supported values: *

    *
  • {@code enabled}: enables timeouts *
  • {@code disabled}: disables timeouts *
  • {@code disabled_on_debug}: disables timeouts while debugging *
* * @since 5.5 */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.7") public @interface Timeout { /** * Property name used to set the default timeout for all testable and * lifecycle methods: {@value}. * *

The value of this property will be used unless overridden by a more * specific property or a {@link Timeout @Timeout} * annotation present on the method or on an enclosing test class (for * testable methods). * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.default"; /** * Property name used to set the default timeout for all testable methods: * {@value}. * *

The value of this property will be used unless overridden by a more * specific property or a {@link Timeout @Timeout} * annotation present on the testable method or on an enclosing test class. * *

This property overrides the {@value #DEFAULT_TIMEOUT_PROPERTY_NAME} * property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.testable.method.default"; /** * Property name used to set the default timeout for all {@link Test @Test} * methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the {@link Test @Test} * method or on an enclosing test class. * *

This property overrides the * {@value #DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.test.method.default"; /** * Property name used to set the default timeout for all * {@link TestTemplate @TestTemplate} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link TestTemplate @TestTemplate} method or on an enclosing test class. * *

This property overrides the * {@value #DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.testtemplate.method.default"; /** * Property name used to set the default timeout for all * {@link TestFactory @TestFactory} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link TestFactory @TestFactory} method or on an enclosing test class. * *

This property overrides the * {@value #DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.testfactory.method.default"; /** * Property name used to set the default timeout for all lifecycle methods: * {@value}. * *

The value of this property will be used unless overridden by a more * specific property or a {@link Timeout @Timeout} annotation present on the * lifecycle method. * *

This property overrides the {@value #DEFAULT_TIMEOUT_PROPERTY_NAME} * property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.lifecycle.method.default"; /** * Property name used to set the default timeout for all * {@link BeforeAll @BeforeAll} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link BeforeAll @BeforeAll} method. * *

This property overrides the * {@value #DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.beforeall.method.default"; /** * Property name used to set the default timeout for all * {@link BeforeEach @BeforeEach} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link BeforeEach @BeforeEach} method. * *

This property overrides the * {@value #DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.beforeeach.method.default"; /** * Property name used to set the default timeout for all * {@link AfterEach @AfterEach} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link AfterEach @AfterEach} method. * *

This property overrides the * {@value #DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.aftereach.method.default"; /** * Property name used to set the default timeout for all * {@link AfterAll @AfterAll} methods: {@value}. * *

The value of this property will be used unless overridden by a * {@link Timeout @Timeout} annotation present on the * {@link AfterAll @AfterAll} method. * *

This property overrides the * {@value #DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME} property. * *

Please refer to the class * description for the definition of supported values. * * @since 5.5 */ @API(status = STABLE, since = "5.9") String DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME = "junit.jupiter.execution.timeout.afterall.method.default"; /** * Property name used to configure whether timeouts are applied to tests: {@value}. * *

The value of this property will be used to toggle whether * {@link Timeout @Timeout} is applied to tests.

* *

Supported timeout mode values:

*
    *
  • {@code enabled}: enables timeouts *
  • {@code disabled}: disables timeouts *
  • {@code disabled_on_debug}: disables timeouts while debugging *
* *

If not specified, the default is {@code enabled}. * * @since 5.6 */ @API(status = STABLE, since = "5.9") String TIMEOUT_MODE_PROPERTY_NAME = "junit.jupiter.execution.timeout.mode"; /** * Property name used to set the default thread mode for all testable and lifecycle * methods: "junit.jupiter.execution.timeout.thread.mode.default". * *

The value of this property will be used unless overridden by a {@link Timeout @Timeout} * annotation present on the method or on an enclosing test class (for testable methods). * *

The supported values are {@code SAME_THREAD} or {@code SEPARATE_THREAD}, if none is provided * {@code SAME_THREAD} is used as default. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") String DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME = "junit.jupiter.execution.timeout.thread.mode.default"; /** * The duration of this timeout. * * @return timeout duration; must be a positive number */ long value(); /** * The time unit of this timeout. * * @return time unit * @see TimeUnit */ TimeUnit unit() default TimeUnit.SECONDS; /** * The thread mode of this timeout. * * @return thread mode * @since 5.9 * @see ThreadMode */ @API(status = EXPERIMENTAL, since = "5.9") ThreadMode threadMode() default ThreadMode.INFERRED; /** * {@code ThreadMode} is use to define whether the test code should be executed in the thread * of the calling code or in a separated thread. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") enum ThreadMode { /** * The thread mode is determined using the parameter configured in property * {@value Timeout#DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME}. */ INFERRED, /** * The test code is executed in the thread of the calling code. */ SAME_THREAD, /** * The test code is executed in a different thread than that of the calling code. Furthermore, * execution of the test code will be preemptively aborted if the timeout is exceeded. See the * {@linkplain Assertions Preemptive Timeouts} section of the class-level * Javadoc for a discussion of possible undesirable side effects. */ SEPARATE_THREAD, } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/000077500000000000000000000000001455764576500274045ustar00rootroot00000000000000AbstractOsBasedExecutionCondition.java000066400000000000000000000043401455764576500367300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.annotation.Annotation; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; /** * Base class for OS-based {@link ExecutionCondition} implementations. * * @since 5.9 */ abstract class AbstractOsBasedExecutionCondition implements ExecutionCondition { static final String CURRENT_ARCHITECTURE = System.getProperty("os.arch"); static final String CURRENT_OS = System.getProperty("os.name"); private final Class annotationType; AbstractOsBasedExecutionCondition(Class annotationType) { this.annotationType = annotationType; } @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return findAnnotation(context.getElement(), this.annotationType) // .map(this::evaluateExecutionCondition) // .orElseGet(this::enabledByDefault); } abstract ConditionEvaluationResult evaluateExecutionCondition(A annotation); String createReason(boolean enabled, boolean osSpecified, boolean archSpecified) { StringBuilder reason = new StringBuilder() // .append(enabled ? "Enabled" : "Disabled") // .append(osSpecified ? " on operating system: " : " on architecture: "); if (osSpecified && archSpecified) { reason.append(String.format("%s (%s)", CURRENT_OS, CURRENT_ARCHITECTURE)); } else if (osSpecified) { reason.append(CURRENT_OS); } else { reason.append(CURRENT_ARCHITECTURE); } return reason.toString(); } private ConditionEvaluationResult enabledByDefault() { String reason = String.format("@%s is not present", this.annotationType.getSimpleName()); return enabled(reason); } } AbstractRepeatableAnnotationCondition.java000066400000000000000000000051411455764576500376230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; import java.lang.reflect.AnnotatedElement; import java.util.Optional; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * Abstract base class for {@link ExecutionCondition} implementations that support * {@linkplain Repeatable repeatable} annotations. * * @param the type of repeatable annotation supported by this {@code ExecutionCondition} * @since 5.6 */ abstract class AbstractRepeatableAnnotationCondition implements ExecutionCondition { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Class annotationType; AbstractRepeatableAnnotationCondition(Class annotationType) { this.annotationType = annotationType; } @Override public final ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { Optional optionalElement = context.getElement(); if (optionalElement.isPresent()) { AnnotatedElement annotatedElement = optionalElement.get(); // @formatter:off return findRepeatableAnnotations(annotatedElement, this.annotationType).stream() .map(annotation -> { ConditionEvaluationResult result = evaluate(annotation); logResult(annotation, annotatedElement, result); return result; }) .filter(ConditionEvaluationResult::isDisabled) .findFirst() .orElse(getNoDisabledConditionsEncounteredResult()); // @formatter:on } return getNoDisabledConditionsEncounteredResult(); } protected abstract ConditionEvaluationResult evaluate(A annotation); protected abstract ConditionEvaluationResult getNoDisabledConditionsEncounteredResult(); private void logResult(A annotation, AnnotatedElement annotatedElement, ConditionEvaluationResult result) { logger.trace(() -> format("Evaluation of %s on [%s] resulted in: %s", annotation, annotatedElement, result)); } } BooleanExecutionCondition.java000066400000000000000000000037451455764576500353130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.annotation.Annotation; import java.util.function.Function; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; abstract class BooleanExecutionCondition implements ExecutionCondition { private final Class annotationType; private final String enabledReason; private final String disabledReason; private final Function customDisabledReason; BooleanExecutionCondition(Class annotationType, String enabledReason, String disabledReason, Function customDisabledReason) { this.annotationType = annotationType; this.enabledReason = enabledReason; this.disabledReason = disabledReason; this.customDisabledReason = customDisabledReason; } abstract boolean isEnabled(A annotation); @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return findAnnotation(context.getElement(), annotationType) // .map(annotation -> isEnabled(annotation) ? enabled(enabledReason) : disabled(disabledReason, customDisabledReason.apply(annotation))) // .orElseGet(this::enabledByDefault); } private ConditionEvaluationResult enabledByDefault() { String reason = String.format("@%s is not present", annotationType.getSimpleName()); return enabled(reason); } } DisabledForJreRange.java000066400000000000000000000105501455764576500337650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledForJreRange} is used to signal that the annotated test class or * test method is only disabled for a specific range of Java Runtime * Environment (JRE) versions from {@link #min} to {@link #max}. * *

When applied at the class level, all test methods within that class will * be disabled on the same specified JRE versions. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

This annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.6 * @see JRE * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(DisabledForJreRangeCondition.class) @API(status = STABLE, since = "5.6") @SuppressWarnings("exports") public @interface DisabledForJreRange { /** * Java Runtime Environment version which is used as the lower boundary * for the version range that determines if the annotated class or method * should be disabled. * *

Defaults to {@link JRE#JAVA_8 JAVA_8}, as this is the lowest * supported JRE version. * * @see JRE */ JRE min() default JRE.JAVA_8; /** * Java Runtime Environment version which is used as the upper boundary * for the version range that determines if the annotated class or method * should be disabled. * *

Defaults to {@link JRE#OTHER OTHER}, as this will always be the highest * possible version. * * @see JRE */ JRE max() default JRE.OTHER; /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } DisabledForJreRangeCondition.java000066400000000000000000000027631455764576500356430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.DISABLED_ON_CURRENT_JRE; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.ENABLED_ON_CURRENT_JRE; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledForJreRange @DisabledForJreRange}. * * @since 5.6 * @see DisabledForJreRange */ class DisabledForJreRangeCondition extends BooleanExecutionCondition { DisabledForJreRangeCondition() { super(DisabledForJreRange.class, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, DisabledForJreRange::disabledReason); } @Override boolean isEnabled(DisabledForJreRange annotation) { JRE min = annotation.min(); JRE max = annotation.max(); Preconditions.condition((min != JRE.JAVA_8 || max != JRE.OTHER), "You must declare a non-default value for min or max in @DisabledForJreRange"); Preconditions.condition(max.compareTo(min) >= 0, "@DisabledForJreRange.min must be less than or equal to @DisabledForJreRange.max"); return !JRE.isCurrentVersionWithinRange(min, max); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIf.java000066400000000000000000000101031455764576500322300ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledIf} is used to signal that the annotated test class or test * method is disabled only if the provided * {@linkplain #value() condition} evaluates to {@code true}. * *

When applied at the class level, all test methods within that class will * be disabled on the same condition. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* * This annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.7 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(DisabledIfCondition.class) @API(status = STABLE, since = "5.7") @SuppressWarnings("exports") public @interface DisabledIf { /** * The name of a method within the test class or in an external class to use * as a condition for the test's or container's execution. * *

Condition methods must be static if located outside the test class or * if {@code @DisabledIf} is used at the class level. * *

A condition method in an external class must be referenced by its * fully qualified method name — for example, * {@code com.example.Conditions#isEncryptionSupported}. */ String value(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. */ String disabledReason() default ""; } DisabledIfCondition.java000066400000000000000000000014311455764576500340240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import org.junit.jupiter.api.extension.ExecutionCondition; /** * {@link ExecutionCondition} for {@link DisabledIf @DisabledIf}. * * @since 5.7 * @see DisabledIf */ class DisabledIfCondition extends MethodBasedCondition { DisabledIfCondition() { super(DisabledIf.class, DisabledIf::value, DisabledIf::disabledReason); } @Override protected boolean isEnabled(boolean methodResult) { return !methodResult; } } DisabledIfEnvironmentVariable.java000066400000000000000000000104311455764576500360500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledIfEnvironmentVariable} is used to signal that the annotated test * class or test method is disabled if the value of the specified * {@linkplain #named environment variable} matches the specified * {@linkplain #matches regular expression}. * *

When declared at the class level, the result will apply to all test methods * within that class as well. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

If the specified environment variable is undefined, the presence of this * annotation will have no effect on whether or not the class or method * is disabled. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

As of JUnit Jupiter 5.6, this annotation is a {@linkplain Repeatable * repeatable} annotation. Consequently, this annotation may be declared multiple * times on an {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., * test interface, test class, or test method). Specifically, this annotation will * be found if it is directly present, indirectly present, or meta-present on a * given element. * * @since 5.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(DisabledIfEnvironmentVariables.class) @ExtendWith(DisabledIfEnvironmentVariableCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface DisabledIfEnvironmentVariable { /** * The name of the environment variable to retrieve. * * @return the environment variable name; never blank * @see System#getenv(String) */ String named(); /** * A regular expression that will be used to match against the retrieved * value of the {@link #named} environment variable. * * @return the regular expression; never blank * @see String#matches(String) * @see java.util.regex.Pattern */ String matches(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } DisabledIfEnvironmentVariableCondition.java000066400000000000000000000051231455764576500377210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledIfEnvironmentVariable @DisabledIfEnvironmentVariable}. * * @since 5.1 * @see DisabledIfEnvironmentVariable */ class DisabledIfEnvironmentVariableCondition extends AbstractRepeatableAnnotationCondition { private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "No @DisabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); DisabledIfEnvironmentVariableCondition() { super(DisabledIfEnvironmentVariable.class); } @Override protected ConditionEvaluationResult getNoDisabledConditionsEncounteredResult() { return ENABLED; } @Override protected ConditionEvaluationResult evaluate(DisabledIfEnvironmentVariable annotation) { String name = annotation.named().trim(); String regex = annotation.matches(); Preconditions.notBlank(name, () -> "The 'named' attribute must not be blank in " + annotation); Preconditions.notBlank(regex, () -> "The 'matches' attribute must not be blank in " + annotation); String actual = getEnvironmentVariable(name); // Nothing to match against? if (actual == null) { return enabled(format("Environment variable [%s] does not exist", name)); } if (actual.matches(regex)) { return disabled(format("Environment variable [%s] with value [%s] matches regular expression [%s]", name, actual, regex), annotation.disabledReason()); } // else return enabled(format("Environment variable [%s] with value [%s] does not match regular expression [%s]", name, actual, regex)); } /** * Get the value of the named environment variable. * *

The default implementation delegates to * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ protected String getEnvironmentVariable(String name) { return System.getenv(name); } } DisabledIfEnvironmentVariables.java000066400000000000000000000032611455764576500362360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @DisabledIfEnvironmentVariables} is a container for one or more * {@link DisabledIfEnvironmentVariable @DisabledIfEnvironmentVariable} declarations. * *

Note, however, that use of the {@code @DisabledIfEnvironmentVariables} container * is completely optional since {@code @DisabledIfEnvironmentVariable} is a {@linkplain * java.lang.annotation.Repeatable repeatable} annotation. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * * @since 5.6 * @see DisabledIfEnvironmentVariable * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.6") public @interface DisabledIfEnvironmentVariables { /** * An array of one or more {@link DisabledIfEnvironmentVariable @DisabledIfEnvironmentVariable} * declarations. */ DisabledIfEnvironmentVariable[] value(); } DisabledIfSystemProperties.java000066400000000000000000000032021455764576500354350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @DisabledIfSystemProperties} is a container for one or more * {@link DisabledIfSystemProperty @DisabledIfSystemProperty} declarations. * *

Note, however, that use of the {@code @DisabledIfSystemProperties} container * is completely optional since {@code @DisabledIfSystemProperty} is a {@linkplain * java.lang.annotation.Repeatable repeatable} annotation. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * * @since 5.6 * @see DisabledIfSystemProperty * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.6") public @interface DisabledIfSystemProperties { /** * An array of one or more {@link DisabledIfSystemProperty @DisabledIfSystemProperty} * declarations. */ DisabledIfSystemProperty[] value(); } DisabledIfSystemProperty.java000066400000000000000000000103771455764576500351400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledIfSystemProperty} is used to signal that the annotated test * class or test method is disabled if the value of the specified * {@linkplain #named system property} matches the specified * {@linkplain #matches regular expression}. * *

When declared at the class level, the result will apply to all test methods * within that class as well. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

If the specified system property is undefined, the presence of this * annotation will have no effect on whether or not the class or method * is disabled. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

As of JUnit Jupiter 5.6, this annotation is a {@linkplain Repeatable * repeatable} annotation. Consequently, this annotation may be declared multiple * times on an {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., * test interface, test class, or test method). Specifically, this annotation will * be found if it is directly present, indirectly present, or meta-present on a * given element. * * @since 5.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(DisabledIfSystemProperties.class) @ExtendWith(DisabledIfSystemPropertyCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface DisabledIfSystemProperty { /** * The name of the JVM system property to retrieve. * * @return the system property name; never blank * @see System#getProperty(String) */ String named(); /** * A regular expression that will be used to match against the retrieved * value of the {@link #named} JVM system property. * * @return the regular expression; never blank * @see String#matches(String) * @see java.util.regex.Pattern */ String matches(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } DisabledIfSystemPropertyCondition.java000066400000000000000000000043561455764576500370070ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledIfSystemProperty @DisabledIfSystemProperty}. * * @since 5.1 * @see DisabledIfSystemProperty */ class DisabledIfSystemPropertyCondition extends AbstractRepeatableAnnotationCondition { private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "No @DisabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); DisabledIfSystemPropertyCondition() { super(DisabledIfSystemProperty.class); } @Override protected ConditionEvaluationResult getNoDisabledConditionsEncounteredResult() { return ENABLED; } @Override protected ConditionEvaluationResult evaluate(DisabledIfSystemProperty annotation) { String name = annotation.named().trim(); String regex = annotation.matches(); Preconditions.notBlank(name, () -> "The 'named' attribute must not be blank in " + annotation); Preconditions.notBlank(regex, () -> "The 'matches' attribute must not be blank in " + annotation); String actual = System.getProperty(name); // Nothing to match against? if (actual == null) { return enabled(format("System property [%s] does not exist", name)); } if (actual.matches(regex)) { return disabled( format("System property [%s] with value [%s] matches regular expression [%s]", name, actual, regex), annotation.disabledReason()); } // else return enabled( format("System property [%s] with value [%s] does not match regular expression [%s]", name, actual, regex)); } } DisabledInNativeImage.java000066400000000000000000000072251455764576500343060ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @DisabledInNativeImage} is used to signal that the annotated test class * or test method is only disabled when executing within a GraalVM native * image. * *

When applied at the class level, all test methods within that class will * be disabled within a native image. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Technical Details

* *

JUnit detects whether tests are executing within a GraalVM native image by * checking for the presence of the {@code org.graalvm.nativeimage.imagecode} * system property (see * org.graalvm.nativeimage.ImageInfo * for details). The GraalVM compiler sets the property to {@code buildtime} while * compiling a native image; the property is set to {@code runtime} while a native * image is executing; and the Gradle and Maven plug-ins in the GraalVM * Native Build Tools * project set the property to {@code agent} while executing tests with the GraalVM * tracing agent. * * @since 5.9.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @DisabledIfSystemProperty(named = "org.graalvm.nativeimage.imagecode", matches = ".+", // disabledReason = "Currently executing within a GraalVM native image") @API(status = STABLE, since = "5.9.1") public @interface DisabledInNativeImage { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java000066400000000000000000000075331455764576500327240ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledOnJre} is used to signal that the annotated test class or * test method is disabled on one or more specified Java * Runtime Environment (JRE) {@linkplain #value versions}. * *

When applied at the class level, all test methods within that class * will be disabled on the same specified JRE versions. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

As of JUnit Jupiter 5.1, this annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.1 * @see JRE * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(DisabledOnJreCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface DisabledOnJre { /** * Java Runtime Environment versions on which the annotated class or * method should be disabled. * * @see JRE */ JRE[] value(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } DisabledOnJreCondition.java000066400000000000000000000024221455764576500345040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.DISABLED_ON_CURRENT_JRE; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.ENABLED_ON_CURRENT_JRE; import java.util.Arrays; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledOnJre @DisabledOnJre}. * * @since 5.1 * @see DisabledOnJre */ class DisabledOnJreCondition extends BooleanExecutionCondition { DisabledOnJreCondition() { super(DisabledOnJre.class, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, DisabledOnJre::disabledReason); } @Override boolean isEnabled(DisabledOnJre annotation) { JRE[] versions = annotation.value(); Preconditions.condition(versions.length > 0, "You must declare at least one JRE in @DisabledOnJre"); return Arrays.stream(versions).noneMatch(JRE::isCurrentVersion); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnOs.java000066400000000000000000000106241455764576500325600ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @DisabledOnOs} is used to signal that the annotated test class or * test method is disabled on one or more specified * {@linkplain #value operating systems} or on one or more specified * {@linkplain #architectures architectures} * *

If operating systems and architectures are specified, the annotated * test class or test method is disabled if both conditions apply. * *

When applied at the class level, all test methods within that class * will be disabled on the same specified operating systems, architectures, or * the specified combinations of both. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

As of JUnit Jupiter 5.1, this annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.1 * @see OS * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(DisabledOnOsCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface DisabledOnOs { /** * Operating systems on which the annotated class or method should be * disabled. * * @see OS */ OS[] value() default {}; /** * Architectures on which the annotated class or method should be disabled. * *

Each architecture will be compared to the value returned from * {@code System.getProperty("os.arch")}, ignoring case. * * @since 5.9 */ @API(status = STABLE, since = "5.9") String[] architectures() default {}; /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } DisabledOnOsCondition.java000066400000000000000000000037161455764576500343540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import java.util.Arrays; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledOnOs @DisabledOnOs}. * * @since 5.1 * @see DisabledOnOs */ class DisabledOnOsCondition extends AbstractOsBasedExecutionCondition { DisabledOnOsCondition() { super(DisabledOnOs.class); } @Override ConditionEvaluationResult evaluateExecutionCondition(DisabledOnOs annotation) { boolean osSpecified = annotation.value().length > 0; boolean archSpecified = annotation.architectures().length > 0; Preconditions.condition(osSpecified || archSpecified, "You must declare at least one OS or architecture in @DisabledOnOs"); boolean enabled = isEnabledBasedOnOs(annotation) || isEnabledBasedOnArchitecture(annotation); String reason = createReason(enabled, osSpecified, archSpecified); return enabled ? ConditionEvaluationResult.enabled(reason) : ConditionEvaluationResult.disabled(reason, annotation.disabledReason()); } private boolean isEnabledBasedOnOs(DisabledOnOs annotation) { OS[] operatingSystems = annotation.value(); if (operatingSystems.length == 0) { return false; } return Arrays.stream(operatingSystems).noneMatch(OS::isCurrentOs); } private boolean isEnabledBasedOnArchitecture(DisabledOnOs annotation) { String[] architectures = annotation.architectures(); if (architectures.length == 0) { return false; } return Arrays.stream(architectures).noneMatch(CURRENT_ARCHITECTURE::equalsIgnoreCase); } } EnabledForJreRange.java000066400000000000000000000105601455764576500336110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledForJreRange} is used to signal that the annotated test class or * test method is only enabled for a specific range of Java Runtime * Environment (JRE) versions from {@link #min} to {@link #max}. * *

When applied at the class level, all test methods within that class will * be enabled on the same specified JRE versions. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

This annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.6 * @see JRE * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(EnabledForJreRangeCondition.class) @API(status = STABLE, since = "5.6") @SuppressWarnings("exports") public @interface EnabledForJreRange { /** * Java Runtime Environment version which should be used as the lower boundary * for the version range that determines if the annotated class or method * should be enabled. * *

Defaults to {@link JRE#JAVA_8 JAVA_8}, as this is the lowest * supported JRE version. * * @see JRE */ JRE min() default JRE.JAVA_8; /** * Java Runtime Environment version which should be used as the upper boundary * for the version range that determines if the annotated class or method * should be enabled. * *

Defaults to {@link JRE#OTHER OTHER}, as this will always be the highest * possible version. * * @see JRE */ JRE max() default JRE.OTHER; /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } EnabledForJreRangeCondition.java000066400000000000000000000027461455764576500354670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.DISABLED_ON_CURRENT_JRE; import static org.junit.jupiter.api.condition.EnabledOnJreCondition.ENABLED_ON_CURRENT_JRE; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link EnabledForJreRange @EnabledForJreRange}. * * @since 5.6 * @see EnabledForJreRange */ class EnabledForJreRangeCondition extends BooleanExecutionCondition { EnabledForJreRangeCondition() { super(EnabledForJreRange.class, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, EnabledForJreRange::disabledReason); } @Override boolean isEnabled(EnabledForJreRange annotation) { JRE min = annotation.min(); JRE max = annotation.max(); Preconditions.condition((min != JRE.JAVA_8 || max != JRE.OTHER), "You must declare a non-default value for min or max in @EnabledForJreRange"); Preconditions.condition(max.compareTo(min) >= 0, "@EnabledForJreRange.min must be less than or equal to @EnabledForJreRange.max"); return JRE.isCurrentVersionWithinRange(min, max); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIf.java000066400000000000000000000100761455764576500320640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledIf} is used to signal that the annotated test class or test * method is enabled only if the provided * {@linkplain #value() condition} evaluates to {@code true}. * *

When applied at the class level, all test methods within that class will * be enabled on the same condition. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* * This annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.7 * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(EnabledIfCondition.class) @API(status = STABLE, since = "5.7") @SuppressWarnings("exports") public @interface EnabledIf { /** * The name of a method within the test class or in an external class to use * as a condition for the test's or container's execution. * *

Condition methods must be static if located outside the test class or * if {@code @EnabledIf} is used at the class level. * *

A condition method in an external class must be referenced by its * fully qualified method name — for example, * {@code com.example.Conditions#isEncryptionSupported}. */ String value(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. */ String disabledReason() default ""; } EnabledIfCondition.java000066400000000000000000000014201455764576500336450ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import org.junit.jupiter.api.extension.ExecutionCondition; /** * {@link ExecutionCondition} for {@link EnabledIf @EnabledIf}. * * @since 5.7 * @see EnabledIf */ class EnabledIfCondition extends MethodBasedCondition { EnabledIfCondition() { super(EnabledIf.class, EnabledIf::value, EnabledIf::disabledReason); } @Override protected boolean isEnabled(boolean methodResult) { return methodResult; } } EnabledIfEnvironmentVariable.java000066400000000000000000000103401455764576500356720ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledIfEnvironmentVariable} is used to signal that the annotated test * class or test method is only enabled if the value of the specified * {@linkplain #named environment variable} matches the specified * {@linkplain #matches regular expression}. * *

When declared at the class level, the result will apply to all test methods * within that class as well. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

If the specified environment variable is undefined, the annotated class or * method will be disabled. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

As of JUnit Jupiter 5.6, this annotation is a {@linkplain Repeatable * repeatable} annotation. Consequently, this annotation may be declared multiple * times on an {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., * test interface, test class, or test method). Specifically, this annotation will * be found if it is directly present, indirectly present, or meta-present on a * given element. * * @since 5.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(EnabledIfEnvironmentVariables.class) @ExtendWith(EnabledIfEnvironmentVariableCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface EnabledIfEnvironmentVariable { /** * The name of the environment variable to retrieve. * * @return the environment variable name; never blank * @see System#getenv(String) */ String named(); /** * A regular expression that will be used to match against the retrieved * value of the {@link #named} environment variable. * * @return the regular expression; never blank * @see String#matches(String) * @see java.util.regex.Pattern */ String matches(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } EnabledIfEnvironmentVariableCondition.java000066400000000000000000000051361455764576500375500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link EnabledIfEnvironmentVariable @EnabledIfEnvironmentVariable}. * * @since 5.1 * @see EnabledIfEnvironmentVariable */ class EnabledIfEnvironmentVariableCondition extends AbstractRepeatableAnnotationCondition { private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "No @EnabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); EnabledIfEnvironmentVariableCondition() { super(EnabledIfEnvironmentVariable.class); } @Override protected ConditionEvaluationResult getNoDisabledConditionsEncounteredResult() { return ENABLED; } @Override protected ConditionEvaluationResult evaluate(EnabledIfEnvironmentVariable annotation) { String name = annotation.named().trim(); String regex = annotation.matches(); Preconditions.notBlank(name, () -> "The 'named' attribute must not be blank in " + annotation); Preconditions.notBlank(regex, () -> "The 'matches' attribute must not be blank in " + annotation); String actual = getEnvironmentVariable(name); // Nothing to match against? if (actual == null) { return disabled(format("Environment variable [%s] does not exist", name), annotation.disabledReason()); } if (actual.matches(regex)) { return enabled(format("Environment variable [%s] with value [%s] matches regular expression [%s]", name, actual, regex)); } return disabled(format("Environment variable [%s] with value [%s] does not match regular expression [%s]", name, actual, regex), annotation.disabledReason()); } /** * Get the value of the named environment variable. * *

The default implementation delegates to * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ protected String getEnvironmentVariable(String name) { return System.getenv(name); } } EnabledIfEnvironmentVariables.java000066400000000000000000000032471455764576500360650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @EnabledIfEnvironmentVariables} is a container for one or more * {@link EnabledIfEnvironmentVariable @EnabledIfEnvironmentVariable} declarations. * *

Note, however, that use of the {@code @EnabledIfEnvironmentVariables} container * is completely optional since {@code @EnabledIfEnvironmentVariable} is a {@linkplain * java.lang.annotation.Repeatable repeatable} annotation. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * * @since 5.6 * @see EnabledIfEnvironmentVariable * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.6") public @interface EnabledIfEnvironmentVariables { /** * An array of one or more {@link EnabledIfEnvironmentVariable @EnabledIfEnvironmentVariable} * declarations. */ EnabledIfEnvironmentVariable[] value(); } EnabledIfSystemProperties.java000066400000000000000000000031701455764576500352640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @EnabledIfSystemProperties} is a container for one or more * {@link EnabledIfSystemProperty @EnabledIfSystemProperty} declarations. * *

Note, however, that use of the {@code @EnabledIfSystemProperties} container * is completely optional since {@code @EnabledIfSystemProperty} is a {@linkplain * java.lang.annotation.Repeatable repeatable} annotation. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * * @since 5.6 * @see EnabledIfSystemProperty * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.6") public @interface EnabledIfSystemProperties { /** * An array of one or more {@link EnabledIfSystemProperty @EnabledIfSystemProperty} * declarations. */ EnabledIfSystemProperty[] value(); } EnabledIfSystemProperty.java000066400000000000000000000103061455764576500347530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledIfSystemProperty} is used to signal that the annotated test * class or test method is only enabled if the value of the specified * {@linkplain #named system property} matches the specified * {@linkplain #matches regular expression}. * *

When declared at the class level, the result will apply to all test methods * within that class as well. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

If the specified system property is undefined, the annotated class or * method will be disabled. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

As of JUnit Jupiter 5.6, this annotation is a {@linkplain Repeatable * repeatable} annotation. Consequently, this annotation may be declared multiple * times on an {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., * test interface, test class, or test method). Specifically, this annotation will * be found if it is directly present, indirectly present, or meta-present on a * given element. * * @since 5.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(EnabledIfSystemProperties.class) @ExtendWith(EnabledIfSystemPropertyCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface EnabledIfSystemProperty { /** * The name of the JVM system property to retrieve. * * @return the system property name; never blank * @see System#getProperty(String) */ String named(); /** * A regular expression that will be used to match against the retrieved * value of the {@link #named} JVM system property. * * @return the regular expression; never blank * @see String#matches(String) * @see java.util.regex.Pattern */ String matches(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } EnabledIfSystemPropertyCondition.java000066400000000000000000000043701455764576500366260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link EnabledIfSystemProperty @EnabledIfSystemProperty}. * * @since 5.1 * @see EnabledIfSystemProperty */ class EnabledIfSystemPropertyCondition extends AbstractRepeatableAnnotationCondition { private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "No @EnabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); EnabledIfSystemPropertyCondition() { super(EnabledIfSystemProperty.class); } @Override protected ConditionEvaluationResult getNoDisabledConditionsEncounteredResult() { return ENABLED; } @Override protected ConditionEvaluationResult evaluate(EnabledIfSystemProperty annotation) { String name = annotation.named().trim(); String regex = annotation.matches(); Preconditions.notBlank(name, () -> "The 'named' attribute must not be blank in " + annotation); Preconditions.notBlank(regex, () -> "The 'matches' attribute must not be blank in " + annotation); String actual = System.getProperty(name); // Nothing to match against? if (actual == null) { return disabled(format("System property [%s] does not exist", name), annotation.disabledReason()); } if (actual.matches(regex)) { return enabled( format("System property [%s] with value [%s] matches regular expression [%s]", name, actual, regex)); } return disabled( format("System property [%s] with value [%s] does not match regular expression [%s]", name, actual, regex), annotation.disabledReason()); } } EnabledInNativeImage.java000066400000000000000000000072251455764576500341310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @EnabledInNativeImage} is used to signal that the annotated test class * or test method is only enabled when executing within a GraalVM native * image. * *

When applied at the class level, all test methods within that class will * be enabled within a native image. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Technical Details

* *

JUnit detects whether tests are executing within a GraalVM native image by * checking for the presence of the {@code org.graalvm.nativeimage.imagecode} * system property (see * org.graalvm.nativeimage.ImageInfo * for details). The GraalVM compiler sets the property to {@code buildtime} while * compiling a native image; the property is set to {@code runtime} while a native * image is executing; and the Gradle and Maven plug-ins in the GraalVM * Native Build Tools * project set the property to {@code agent} while executing tests with the GraalVM * tracing agent. * * @since 5.9.1 * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @EnabledIfSystemProperty(named = "org.graalvm.nativeimage.imagecode", matches = ".+", // disabledReason = "Not currently executing within a GraalVM native image") @API(status = STABLE, since = "5.9.1") public @interface EnabledInNativeImage { } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java000066400000000000000000000075321455764576500325460ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledOnJre} is used to signal that the annotated test class or * test method is only enabled on one or more specified Java * Runtime Environment (JRE) {@linkplain #value versions}. * *

When applied at the class level, all test methods within that class * will be enabled on the same specified JRE versions. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

As of JUnit Jupiter 5.1, this annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.1 * @see JRE * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(EnabledOnJreCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface EnabledOnJre { /** * Java Runtime Environment versions on which the annotated class or * method should be enabled. * * @see JRE */ JRE[] value(); /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } EnabledOnJreCondition.java000066400000000000000000000024711455764576500343330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import java.util.Arrays; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link EnabledOnJre @EnabledOnJre}. * * @since 5.1 * @see EnabledOnJre */ class EnabledOnJreCondition extends BooleanExecutionCondition { static final String ENABLED_ON_CURRENT_JRE = // "Enabled on JRE version: " + System.getProperty("java.version"); static final String DISABLED_ON_CURRENT_JRE = // "Disabled on JRE version: " + System.getProperty("java.version"); EnabledOnJreCondition() { super(EnabledOnJre.class, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, EnabledOnJre::disabledReason); } @Override boolean isEnabled(EnabledOnJre annotation) { JRE[] versions = annotation.value(); Preconditions.condition(versions.length > 0, "You must declare at least one JRE in @EnabledOnJre"); return Arrays.stream(versions).anyMatch(JRE::isCurrentVersion); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnOs.java000066400000000000000000000106201455764576500323770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @EnabledOnOs} is used to signal that the annotated test class or * test method is only enabled on one or more specified * {@linkplain #value operating systems} or one or more specified * {@linkplain #architectures architectures}. * *

If operating systems and architectures are specified, the annotated * test class or test method is enabled if both conditions apply. * *

When applied at the class level, all test methods within that class * will be enabled on the same specified operating systems, architectures, or * the specified combinations of both. * *

This annotation is not {@link java.lang.annotation.Inherited @Inherited}. * Consequently, if you wish to apply the same semantics to a subclass, this * annotation must be redeclared on the subclass. * *

If a test method is disabled via this annotation, that does not prevent * the test class from being instantiated. Rather, it prevents the execution of * the test method and method-level lifecycle callbacks such as {@code @BeforeEach} * methods, {@code @AfterEach} methods, and corresponding extension APIs. * *

This annotation may be used as a meta-annotation in order to create a * custom composed annotation that inherits the semantics of this * annotation. * *

Warning

* *

As of JUnit Jupiter 5.1, this annotation can only be declared once on an * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} (i.e., test * interface, test class, or test method). If this annotation is directly * present, indirectly present, or meta-present multiple times on a given * element, only the first such annotation discovered by JUnit will be used; * any additional declarations will be silently ignored. Note, however, that * this annotation may be used in conjunction with other {@code @Enabled*} or * {@code @Disabled*} annotations in this package. * * @since 5.1 * @see OS * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable * @see org.junit.jupiter.api.Disabled */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @ExtendWith(EnabledOnOsCondition.class) @API(status = STABLE, since = "5.1") @SuppressWarnings("exports") public @interface EnabledOnOs { /** * Operating systems on which the annotated class or method should be * enabled. * * @see OS */ OS[] value() default {}; /** * Architectures on which the annotated class or method should be enabled. * *

Each architecture will be compared to the value returned from * {@code System.getProperty("os.arch")}, ignoring case. * * @since 5.9 */ @API(status = STABLE, since = "5.9") String[] architectures() default {}; /** * Custom reason to provide if the test or container is disabled. * *

If a custom reason is supplied, it will be combined with the default * reason for this annotation. If a custom reason is not supplied, the default * reason will be used. * * @since 5.7 */ @API(status = STABLE, since = "5.7") String disabledReason() default ""; } EnabledOnOsCondition.java000066400000000000000000000036771455764576500342050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import java.util.Arrays; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link EnabledOnOs @EnabledOnOs}. * * @since 5.1 * @see EnabledOnOs */ class EnabledOnOsCondition extends AbstractOsBasedExecutionCondition { EnabledOnOsCondition() { super(EnabledOnOs.class); } @Override ConditionEvaluationResult evaluateExecutionCondition(EnabledOnOs annotation) { boolean osSpecified = annotation.value().length > 0; boolean archSpecified = annotation.architectures().length > 0; Preconditions.condition(osSpecified || archSpecified, "You must declare at least one OS or architecture in @EnabledOnOs"); boolean enabled = isEnabledBasedOnOs(annotation) && isEnabledBasedOnArchitecture(annotation); String reason = createReason(enabled, osSpecified, archSpecified); return enabled ? ConditionEvaluationResult.enabled(reason) : ConditionEvaluationResult.disabled(reason, annotation.disabledReason()); } private boolean isEnabledBasedOnOs(EnabledOnOs annotation) { OS[] operatingSystems = annotation.value(); if (operatingSystems.length == 0) { return true; } return Arrays.stream(operatingSystems).anyMatch(OS::isCurrentOs); } private boolean isEnabledBasedOnArchitecture(EnabledOnOs annotation) { String[] architectures = annotation.architectures(); if (architectures.length == 0) { return true; } return Arrays.stream(architectures).anyMatch(CURRENT_ARCHITECTURE::equalsIgnoreCase); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/JRE.java000066400000000000000000000124301455764576500306670ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; import java.util.EnumSet; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; /** * Enumeration of Java Runtime Environment (JRE) versions. * *

If the current JRE version cannot be detected — for example, if the * {@code java.version} JVM system property is undefined — then none of * the constants defined in this enum will be considered to be the * {@linkplain #isCurrentVersion current JRE version}. * * @since 5.1 * @see #JAVA_8 * @see #JAVA_9 * @see #JAVA_10 * @see #JAVA_11 * @see #JAVA_12 * @see #JAVA_13 * @see #JAVA_14 * @see #JAVA_15 * @see #JAVA_16 * @see #JAVA_17 * @see #JAVA_18 * @see #JAVA_19 * @see #JAVA_20 * @see #JAVA_21 * @see #JAVA_22 * @see #OTHER * @see EnabledOnJre * @see DisabledOnJre * @see EnabledForJreRange * @see DisabledForJreRange */ @API(status = STABLE, since = "5.1") public enum JRE { /** * Java 8. */ JAVA_8, /** * Java 9. */ JAVA_9, /** * Java 10. */ JAVA_10, /** * Java 11. */ JAVA_11, /** * Java 12. * * @since 5.4 */ @API(status = STABLE, since = "5.4") JAVA_12, /** * Java 13. * * @since 5.4 */ @API(status = STABLE, since = "5.4") JAVA_13, /** * Java 14. * * @since 5.5 */ @API(status = STABLE, since = "5.5") JAVA_14, /** * Java 15. * * @since 5.6 */ @API(status = STABLE, since = "5.6") JAVA_15, /** * Java 16. * * @since 5.7 */ @API(status = STABLE, since = "5.7") JAVA_16, /** * Java 17. * * @since 5.7.1 */ @API(status = STABLE, since = "5.7.1") JAVA_17, /** * Java 18. * * @since 5.8.1 */ @API(status = STABLE, since = "5.8.1") JAVA_18, /** * Java 19. * * @since 5.9 */ @API(status = STABLE, since = "5.9") JAVA_19, /** * Java 20. * * @since 5.9 */ @API(status = STABLE, since = "5.9") JAVA_20, /** * Java 21. * * @since 5.9.2 */ @API(status = STABLE, since = "5.9.2") JAVA_21, /** * Java 22. * * @since 5.10 */ @API(status = STABLE, since = "5.10") JAVA_22, /** * A JRE version other than {@link #JAVA_8}, {@link #JAVA_9}, * {@link #JAVA_10}, {@link #JAVA_11}, {@link #JAVA_12}, * {@link #JAVA_13}, {@link #JAVA_14}, {@link #JAVA_15}, * {@link #JAVA_16}, {@link #JAVA_17}, {@link #JAVA_18}, * {@link #JAVA_19}, {@link #JAVA_20}, {@link #JAVA_21}, or * {@link #JAVA_22}. */ OTHER; private static final Logger logger = LoggerFactory.getLogger(JRE.class); private static final JRE CURRENT_VERSION = determineCurrentVersion(); private static JRE determineCurrentVersion() { String javaVersion = System.getProperty("java.version"); boolean javaVersionIsBlank = StringUtils.isBlank(javaVersion); if (javaVersionIsBlank) { logger.debug( () -> "JVM system property 'java.version' is undefined. It is therefore not possible to detect Java 8."); } if (!javaVersionIsBlank && javaVersion.startsWith("1.8")) { return JAVA_8; } try { // java.lang.Runtime.version() is a static method available on Java 9+ // that returns an instance of java.lang.Runtime.Version which has the // following method: public int major() Method versionMethod = Runtime.class.getMethod("version"); Object version = ReflectionUtils.invokeMethod(versionMethod, null); Method majorMethod = version.getClass().getMethod("major"); int major = (int) ReflectionUtils.invokeMethod(majorMethod, version); switch (major) { case 9: return JAVA_9; case 10: return JAVA_10; case 11: return JAVA_11; case 12: return JAVA_12; case 13: return JAVA_13; case 14: return JAVA_14; case 15: return JAVA_15; case 16: return JAVA_16; case 17: return JAVA_17; case 18: return JAVA_18; case 19: return JAVA_19; case 20: return JAVA_20; case 21: return JAVA_21; case 22: return JAVA_22; default: return OTHER; } } catch (Exception ex) { logger.debug(ex, () -> "Failed to determine the current JRE version via java.lang.Runtime.Version."); } // null signals that the current JRE version is "unknown" return null; } /** * @return {@code true} if this {@code JRE} is known to be the * Java Runtime Environment version for the currently executing JVM or if * the version is {@link #OTHER} */ public boolean isCurrentVersion() { return this == CURRENT_VERSION; } /** * @return the {@link JRE} for the currently executing JVM, potentially * {@link #OTHER} * * @since 5.7 */ @API(status = STABLE, since = "5.7") public static JRE currentVersion() { return CURRENT_VERSION; } static boolean isCurrentVersionWithinRange(JRE min, JRE max) { return EnumSet.range(min, max).contains(CURRENT_VERSION); } } MethodBasedCondition.java000066400000000000000000000114141455764576500342170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; /** * @since 5.7 */ abstract class MethodBasedCondition implements ExecutionCondition { private final Class annotationType; private final Function methodName; private final Function customDisabledReason; MethodBasedCondition(Class annotationType, Function methodName, Function customDisabledReason) { this.annotationType = annotationType; this.methodName = methodName; this.customDisabledReason = customDisabledReason; } @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { Optional annotation = findAnnotation(context.getElement(), this.annotationType); return annotation // .map(this.methodName) // .map(methodName -> getConditionMethod(methodName, context)) // .map(method -> invokeConditionMethod(method, context)) // .map(methodResult -> buildConditionEvaluationResult(methodResult, annotation.get())) // .orElseGet(this::enabledByDefault); } // package-private for testing Method getConditionMethod(String fullyQualifiedMethodName, ExtensionContext context) { Class testClass = context.getRequiredTestClass(); if (!fullyQualifiedMethodName.contains("#")) { return findMethod(testClass, fullyQualifiedMethodName); } String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); String className = methodParts[0]; String methodName = methodParts[1]; ClassLoader classLoader = ClassLoaderUtils.getClassLoader(testClass); Class clazz = ReflectionUtils.tryToLoadClass(className, classLoader).getOrThrow( cause -> new JUnitException(format("Could not load class [%s]", className), cause)); return findMethod(clazz, methodName); } private Method findMethod(Class clazz, String methodName) { return ReflectionUtils.findMethod(clazz, methodName) // .orElseGet(() -> ReflectionUtils.getRequiredMethod(clazz, methodName, ExtensionContext.class)); } private boolean invokeConditionMethod(Method method, ExtensionContext context) { Preconditions.condition(method.getReturnType() == boolean.class, () -> format("Method [%s] must return a boolean", method)); Preconditions.condition(acceptsExtensionContextOrNoArguments(method), () -> format("Method [%s] must accept either an ExtensionContext or no arguments", method)); Object testInstance = context.getTestInstance().orElse(null); if (method.getParameterCount() == 0) { return (boolean) ReflectionUtils.invokeMethod(method, testInstance); } return (boolean) ReflectionUtils.invokeMethod(method, testInstance, context); } private boolean acceptsExtensionContextOrNoArguments(Method method) { int parameterCount = method.getParameterCount(); return parameterCount == 0 || (parameterCount == 1 && method.getParameterTypes()[0] == ExtensionContext.class); } private ConditionEvaluationResult buildConditionEvaluationResult(boolean methodResult, A annotation) { Supplier defaultReason = () -> format("@%s(\"%s\") evaluated to %s", this.annotationType.getSimpleName(), this.methodName.apply(annotation), methodResult); if (isEnabled(methodResult)) { return enabled(defaultReason.get()); } String customReason = this.customDisabledReason.apply(annotation); return StringUtils.isNotBlank(customReason) ? disabled(customReason) : disabled(defaultReason.get()); } protected abstract boolean isEnabled(boolean methodResult); private ConditionEvaluationResult enabledByDefault() { return enabled(format("@%s is not present", this.annotationType.getSimpleName())); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java000066400000000000000000000064031455764576500305730ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.apiguardian.api.API.Status.STABLE; import java.util.Locale; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.StringUtils; /** * Enumeration of common operating systems used for testing Java applications. * *

If the current operating system cannot be detected — for example, * if the {@code os.name} JVM system property is undefined — then none * of the constants defined in this enum will be considered to be the * {@linkplain #isCurrentOs current operating system}. * * @since 5.1 * @see #AIX * @see #FREEBSD * @see #LINUX * @see #MAC * @see #OPENBSD * @see #SOLARIS * @see #WINDOWS * @see #OTHER * @see EnabledOnOs * @see DisabledOnOs */ @API(status = STABLE, since = "5.1") public enum OS { /** * IBM AIX operating system. * * @since 5.3 */ @API(status = STABLE, since = "5.3") AIX, /** * FreeBSD operating system. * * @since 5.9 */ @API(status = STABLE, since = "5.9") FREEBSD, /** * Linux-based operating system. */ LINUX, /** * Apple Macintosh operating system (e.g., macOS). */ MAC, /** * OpenBSD operating system. * * @since 5.9 */ @API(status = STABLE, since = "5.9") OPENBSD, /** * Oracle Solaris operating system. */ SOLARIS, /** * Microsoft Windows operating system. */ WINDOWS, /** * An operating system other than {@link #AIX}, {@link #FREEBSD}, {@link #LINUX}, * {@link #MAC}, {@link #OPENBSD}, {@link #SOLARIS}, or {@link #WINDOWS}. */ OTHER; private static final Logger logger = LoggerFactory.getLogger(OS.class); private static final OS CURRENT_OS = determineCurrentOs(); /** * Get the current operating system. * * @since 5.9 */ @API(status = STABLE, since = "5.10") public static OS current() { return CURRENT_OS; } private static OS determineCurrentOs() { return parse(System.getProperty("os.name")); } static OS parse(String osName) { if (StringUtils.isBlank(osName)) { logger.debug( () -> "JVM system property 'os.name' is undefined. It is therefore not possible to detect the current OS."); // null signals that the current OS is "unknown" return null; } osName = osName.toLowerCase(Locale.ENGLISH); if (osName.contains("aix")) { return AIX; } if (osName.contains("freebsd")) { return FREEBSD; } if (osName.contains("linux")) { return LINUX; } if (osName.contains("mac")) { return MAC; } if (osName.contains("openbsd")) { return OPENBSD; } if (osName.contains("sunos") || osName.contains("solaris")) { return SOLARIS; } if (osName.contains("win")) { return WINDOWS; } return OTHER; } /** * @return {@code true} if this {@code OS} is known to be the * operating system on which the current JVM is executing */ public boolean isCurrentOs() { return this == CURRENT_OS; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/package-info.java000066400000000000000000000002031455764576500325660ustar00rootroot00000000000000/** * Annotation-based conditions for enabling or disabling tests in JUnit Jupiter. */ package org.junit.jupiter.api.condition; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/000077500000000000000000000000001455764576500274325ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AfterAllCallback.java000066400000000000000000000047501455764576500334120ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code AfterAllCallback} defines the API for {@link Extension Extensions} * that wish to provide additional behavior to test containers once * after all tests in the container have been executed. * *

Concrete implementations often implement {@link BeforeAllCallback} as well. * *

Extensions that implement {@code AfterAllCallback} must be registered at * the class level. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.AfterAll * @see BeforeAllCallback * @see BeforeEachCallback * @see AfterEachCallback * @see BeforeTestExecutionCallback * @see AfterTestExecutionCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface AfterAllCallback extends Extension { /** * Callback that is invoked once after all tests in the current * container. * * @param context the current extension context; never {@code null} */ void afterAll(ExtensionContext context) throws Exception; } AfterEachCallback.java000066400000000000000000000054361455764576500334650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code AfterEachCallback} defines the API for {@link Extension Extensions} * that wish to provide additional behavior to tests after an individual test * and any user-defined teardown methods (e.g., * {@link org.junit.jupiter.api.AfterEach @AfterEach} methods) for that test * have been executed. * *

Concrete implementations often implement {@link BeforeEachCallback} as well. * If you do not wish to have your callbacks wrapped around user-defined * setup and teardown methods, implement {@link BeforeTestExecutionCallback} and * {@link AfterTestExecutionCallback} instead of {@link BeforeEachCallback} and * {@link AfterEachCallback}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.AfterEach * @see BeforeEachCallback * @see BeforeTestExecutionCallback * @see AfterTestExecutionCallback * @see BeforeAllCallback * @see AfterAllCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface AfterEachCallback extends Extension { /** * Callback that is invoked after an individual test and any * user-defined teardown methods for that test have been executed. * * @param context the current extension context; never {@code null} */ void afterEach(ExtensionContext context) throws Exception; } AfterTestExecutionCallback.java000066400000000000000000000056171455764576500354310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code AfterTestExecutionCallback} defines the API for {@link Extension * Extensions} that wish to provide additional behavior to tests * immediately after an individual test has been executed but * before any user-defined teardown methods (e.g., * {@link org.junit.jupiter.api.AfterEach @AfterEach} methods) have been executed * for that test. * *

Concrete implementations often implement {@link BeforeTestExecutionCallback} * as well. If you wish to have your callbacks wrapped around user-defined * setup and teardown methods, implement {@link BeforeEachCallback} and * {@link AfterEachCallback} instead of {@link BeforeTestExecutionCallback} and * {@link AfterTestExecutionCallback}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.Test * @see BeforeTestExecutionCallback * @see BeforeEachCallback * @see AfterEachCallback * @see BeforeAllCallback * @see AfterAllCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface AfterTestExecutionCallback extends Extension { /** * Callback that is invoked immediately after an individual test has * been executed but before any user-defined teardown methods have been * executed for that test. * * @param context the current extension context; never {@code null} */ void afterTestExecution(ExtensionContext context) throws Exception; } AnnotatedElementContext.java000066400000000000000000000104061455764576500350130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.support.AnnotationSupport; /** * {@code AnnotatedElementContext} encapsulates the context in which an * {@link #getAnnotatedElement() AnnotatedElement} is declared. * *

For example, an {@code AnnotatedElementContext} is used in * {@link org.junit.jupiter.api.io.TempDirFactory TempDirFactory} to allow inspecting * the field or parameter the {@link org.junit.jupiter.api.io.TempDir TempDir} * annotation is declared on. * *

This interface is not intended to be implemented by clients. * * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") public interface AnnotatedElementContext { /** * Get the {@link AnnotatedElement} for this context. * *

WARNING

*

When searching for annotations on the annotated element in this context, * favor {@link #isAnnotated(Class)}, {@link #findAnnotation(Class)}, and * {@link #findRepeatableAnnotations(Class)} over methods in the * {@link AnnotatedElement} API due to a bug in {@code javac} on JDK versions prior * to JDK 9. * * @return the annotated element; never {@code null} */ AnnotatedElement getAnnotatedElement(); /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the {@link AnnotatedElement} for * this context. * *

WARNING

*

Favor the use of this method over directly invoking * {@link AnnotatedElement#isAnnotationPresent(Class)} due to a bug in {@code javac} * on JDK versions prior to JDK 9. * * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @see #findAnnotation(Class) * @see #findRepeatableAnnotations(Class) */ default boolean isAnnotated(Class annotationType) { return AnnotationSupport.isAnnotated(getAnnotatedElement(), annotationType); } /** * Find the first annotation of {@code annotationType} that is either * present or meta-present on the {@link AnnotatedElement} for * this context. * *

WARNING

*

Favor the use of this method over directly invoking annotation lookup * methods in the {@link AnnotatedElement} API due to a bug in {@code javac} on JDK * versions prior to JDK 9. * * @param the annotation type * @param annotationType the annotation type to search for; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @see #isAnnotated(Class) * @see #findRepeatableAnnotations(Class) */ default Optional findAnnotation(Class annotationType) { return AnnotationSupport.findAnnotation(getAnnotatedElement(), annotationType); } /** * Find all repeatable {@linkplain Annotation annotations} of * {@code annotationType} that are either present or * meta-present on the {@link AnnotatedElement} for this context. * *

WARNING

*

Favor the use of this method over directly invoking annotation lookup * methods in the {@link AnnotatedElement} API due to a bug in {@code javac} on JDK * versions prior to JDK 9. * * @param the annotation type * @param annotationType the repeatable annotation type to search for; never * {@code null} * @return the list of all such annotations found; neither {@code null} nor * mutable, but potentially empty * @see #isAnnotated(Class) * @see #findAnnotation(Class) * @see java.lang.annotation.Repeatable */ default List findRepeatableAnnotations(Class annotationType) { return AnnotationSupport.findRepeatableAnnotations(getAnnotatedElement(), annotationType); } } BeforeAllCallback.java000066400000000000000000000047551455764576500335010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code BeforeAllCallback} defines the API for {@link Extension Extensions} * that wish to provide additional behavior to test containers once * before all tests in the container have been executed. * *

Concrete implementations often implement {@link AfterAllCallback} as well. * *

Extensions that implement {@code BeforeAllCallback} must be registered at * the class level. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.BeforeAll * @see AfterAllCallback * @see BeforeEachCallback * @see AfterEachCallback * @see BeforeTestExecutionCallback * @see AfterTestExecutionCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface BeforeAllCallback extends Extension { /** * Callback that is invoked once before all tests in the current * container. * * @param context the current extension context; never {@code null} */ void beforeAll(ExtensionContext context) throws Exception; } BeforeEachCallback.java000066400000000000000000000054361455764576500336260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code BeforeEachCallback} defines the API for {@link Extension Extensions} * that wish to provide additional behavior to tests before an individual test * and any user-defined setup methods (e.g., * {@link org.junit.jupiter.api.BeforeEach @BeforeEach} methods) for that test * have been executed. * *

Concrete implementations often implement {@link AfterEachCallback} as well. * If you do not wish to have your callbacks wrapped around user-defined * setup and teardown methods, implement {@link BeforeTestExecutionCallback} and * {@link AfterTestExecutionCallback} instead of {@link BeforeEachCallback} and * {@link AfterEachCallback}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.BeforeEach * @see AfterEachCallback * @see BeforeTestExecutionCallback * @see AfterTestExecutionCallback * @see BeforeAllCallback * @see AfterAllCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface BeforeEachCallback extends Extension { /** * Callback that is invoked before an individual test and any * user-defined setup methods for that test have been executed. * * @param context the current extension context; never {@code null} */ void beforeEach(ExtensionContext context) throws Exception; } BeforeTestExecutionCallback.java000066400000000000000000000056001455764576500355620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code BeforeTestExecutionCallback} defines the API for {@link Extension * Extensions} that wish to provide additional behavior to tests * immediately before an individual test is executed but after * any user-defined setup methods (e.g., * {@link org.junit.jupiter.api.BeforeEach @BeforeEach} methods) have been * executed for that test. * *

Concrete implementations often implement {@link AfterTestExecutionCallback} * as well. If you wish to have your callbacks wrapped around user-defined * setup and teardown methods, implement {@link BeforeEachCallback} and * {@link AfterEachCallback} instead of {@link BeforeTestExecutionCallback} and * {@link AfterTestExecutionCallback}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * *

Wrapping Behavior

* *

JUnit Jupiter guarantees wrapping behavior for multiple * registered extensions that implement lifecycle callbacks such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link BeforeEachCallback}, {@link AfterEachCallback}, * {@link BeforeTestExecutionCallback}, and {@link AfterTestExecutionCallback}. * *

That means that, given two extensions {@code Extension1} and * {@code Extension2} with {@code Extension1} registered before * {@code Extension2}, any "before" callbacks implemented by {@code Extension1} * are guaranteed to execute before any "before" callbacks implemented by * {@code Extension2}. Similarly, given the two same two extensions registered * in the same order, any "after" callbacks implemented by {@code Extension1} * are guaranteed to execute after any "after" callbacks implemented by * {@code Extension2}. {@code Extension1} is therefore said to wrap * {@code Extension2}. * * @since 5.0 * @see org.junit.jupiter.api.Test * @see AfterTestExecutionCallback * @see BeforeEachCallback * @see AfterEachCallback * @see BeforeAllCallback * @see AfterAllCallback */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface BeforeTestExecutionCallback extends Extension { /** * Callback that is invoked immediately before an individual test is * executed but after any user-defined setup methods have been executed * for that test. * * @param context the current extension context; never {@code null} */ void beforeTestExecution(ExtensionContext context) throws Exception; } ConditionEvaluationResult.java000066400000000000000000000055061455764576500354010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.ToStringBuilder; /** * The result of evaluating an {@link ExecutionCondition}. * * @since 5.0 */ @API(status = STABLE, since = "5.0") public class ConditionEvaluationResult { /** * Factory for creating enabled results. * * @param reason the reason why the container or test should be enabled * @return an enabled {@code ConditionEvaluationResult} with the given reason */ public static ConditionEvaluationResult enabled(String reason) { return new ConditionEvaluationResult(true, reason); } /** * Factory for creating disabled results. * * @param reason the reason why the container or test should be disabled * @return a disabled {@code ConditionEvaluationResult} with the given reason */ public static ConditionEvaluationResult disabled(String reason) { return new ConditionEvaluationResult(false, reason); } /** * Factory for creating disabled results with custom reasons * added by the user. * * @param reason the default reason why the container or test should be disabled * @param customReason the custom reason why the container or test should be disabled * @return a disabled {@code ConditionEvaluationResult} with the given reasons * @since 5.7 */ @API(status = STABLE, since = "5.7") public static ConditionEvaluationResult disabled(String reason, String customReason) { if (StringUtils.isBlank(customReason)) { return disabled(reason); } return disabled(String.format("%s ==> %s", reason, customReason)); } private final boolean enabled; private final Optional reason; private ConditionEvaluationResult(boolean enabled, String reason) { this.enabled = enabled; this.reason = Optional.ofNullable(reason); } /** * Whether the container or test should be disabled. * * @return {@code true} if the container or test should be disabled */ public boolean isDisabled() { return !this.enabled; } /** * Get the reason why the container or test should be enabled or disabled, * if available. */ public Optional getReason() { return this.reason; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("enabled", this.enabled) .append("reason", this.reason.orElse("")) .toString(); // @formatter:on } } DynamicTestInvocationContext.java000066400000000000000000000017761455764576500360540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; import org.junit.jupiter.api.function.Executable; /** * {@code DynamicTestInvocationContext} represents the context of a * single invocation of a {@linkplain org.junit.jupiter.api.DynamicTest * dynamic test}. * * @since 5.8 * @see org.junit.jupiter.api.DynamicTest */ @API(status = EXPERIMENTAL, since = "5.8") public interface DynamicTestInvocationContext { /** * Get the {@code Executable} of this dynamic test invocation context. * * @return the executable of the dynamic test invocation, never {@code null} */ Executable getExecutable(); } ExecutableInvoker.java000066400000000000000000000042531455764576500336410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.apiguardian.api.API; /** * {@code ExecutableInvoker} allows invoking methods and constructors * with support for dynamic resolution of parameters via * {@link ParameterResolver ParameterResolvers}. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") public interface ExecutableInvoker { /** * Invoke the supplied {@code static} method with dynamic parameter resolution. * * @param method the method to invoke and resolve parameters for * @see #invoke(Method, Object) */ default Object invoke(Method method) { return invoke(method, null); } /** * Invoke the supplied method with dynamic parameter resolution. * * @param method the method to invoke and resolve parameters for * @param target the target on which the executable will be invoked; * can be {@code null} for {@code static} methods */ Object invoke(Method method, Object target); /** * Invoke the supplied top-level constructor with dynamic parameter resolution. * * @param constructor the constructor to invoke and resolve parameters for * @see #invoke(Constructor, Object) */ default T invoke(Constructor constructor) { return invoke(constructor, null); } /** * Invoke the supplied constructor with the supplied outer instance and * dynamic parameter resolution. * *

Use this method when invoking the constructor for an inner class. * * @param constructor the constructor to invoke and resolve parameters for * @param outerInstance the outer instance to supply as the first argument * to the constructor; must be {@code null} for top-level classes * or {@code static} nested classes */ T invoke(Constructor constructor, Object outerInstance); } ExecutionCondition.java000066400000000000000000000055311455764576500340340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code ExecutionCondition} defines the {@link Extension} API for * programmatic, conditional test execution. * *

An {@code ExecutionCondition} is * {@linkplain #evaluateExecutionCondition(ExtensionContext) evaluated} * to determine if a given container or test should be executed based on the * supplied {@link ExtensionContext}. * *

If an {@code ExecutionCondition} {@linkplain ConditionEvaluationResult#disabled * disables} a test method, that does not prevent the test class from being * instantiated. Rather, it prevents the execution of the test method and * method-level lifecycle callbacks such as {@code @BeforeEach} methods, * {@code @AfterEach} methods, and corresponding extension APIs. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.0 * @see org.junit.jupiter.api.Disabled * @see org.junit.jupiter.api.condition.EnabledIf * @see org.junit.jupiter.api.condition.DisabledIf * @see org.junit.jupiter.api.condition.EnabledOnOs * @see org.junit.jupiter.api.condition.DisabledOnOs * @see org.junit.jupiter.api.condition.EnabledOnJre * @see org.junit.jupiter.api.condition.DisabledOnJre * @see org.junit.jupiter.api.condition.EnabledForJreRange * @see org.junit.jupiter.api.condition.DisabledForJreRange * @see org.junit.jupiter.api.condition.EnabledInNativeImage * @see org.junit.jupiter.api.condition.DisabledInNativeImage * @see org.junit.jupiter.api.condition.EnabledIfSystemProperty * @see org.junit.jupiter.api.condition.DisabledIfSystemProperty * @see org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable * @see org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface ExecutionCondition extends Extension { /** * Evaluate this condition for the supplied {@link ExtensionContext}. * *

An {@linkplain ConditionEvaluationResult#enabled enabled} result * indicates that the container or test should be executed; whereas, a * {@linkplain ConditionEvaluationResult#disabled disabled} result * indicates that the container or test should not be executed. * * @param context the current extension context; never {@code null} * @return the result of evaluating this condition; never {@code null} */ ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtendWith.java000066400000000000000000000100711455764576500323570ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ExtendWith} is a {@linkplain Repeatable repeatable} annotation * that is used to register {@linkplain Extension extensions} for the annotated * test class, test interface, test method, parameter, or field. * *

Annotated parameters are supported in test class constructors, in test * methods, and in {@code @BeforeAll}, {@code @AfterAll}, {@code @BeforeEach}, * and {@code @AfterEach} lifecycle methods. * *

{@code @ExtendWith} fields may be either {@code static} or non-static. * *

Inheritance

* *

{@code @ExtendWith} fields are inherited from superclasses as long as they * are not hidden or overridden. Furthermore, {@code @ExtendWith} * fields from superclasses will be registered before {@code @ExtendWith} fields * in subclasses. * *

Registration Order

* *

When {@code @ExtendWith} is present on a test class, test interface, or * test method or on a parameter in a test method or lifecycle method, the * corresponding extensions will be registered in the order in which the * {@code @ExtendWith} annotations are discovered. For example, if a test class * is annotated with {@code @ExtendWith(A.class)} and then with * {@code @ExtendWith(B.class)}, extension {@code A} will be registered before * extension {@code B}. * *

By default, if multiple extensions are registered on fields via * {@code @ExtendWith}, they will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute extensions in the same order, thereby allowing for * repeatable builds. However, there are times when extensions need to be * registered in an explicit order. To achieve that, you can annotate * {@code @ExtendWith} fields with {@link org.junit.jupiter.api.Order @Order}. * Any {@code @ExtendWith} field not annotated with {@code @Order} will be * ordered using the {@link org.junit.jupiter.api.Order#DEFAULT default} order * value. Note that {@code @RegisterExtension} fields can also be ordered with * {@code @Order}, relative to {@code @ExtendWith} fields and other * {@code @RegisterExtension} fields. * *

Supported Extension APIs

* *
    *
  • {@link ExecutionCondition}
  • *
  • {@link InvocationInterceptor}
  • *
  • {@link BeforeAllCallback}
  • *
  • {@link AfterAllCallback}
  • *
  • {@link BeforeEachCallback}
  • *
  • {@link AfterEachCallback}
  • *
  • {@link BeforeTestExecutionCallback}
  • *
  • {@link AfterTestExecutionCallback}
  • *
  • {@link TestInstanceFactory}
  • *
  • {@link TestInstancePostProcessor}
  • *
  • {@link TestInstancePreConstructCallback}
  • *
  • {@link TestInstancePreDestroyCallback}
  • *
  • {@link ParameterResolver}
  • *
  • {@link LifecycleMethodExecutionExceptionHandler}
  • *
  • {@link TestExecutionExceptionHandler}
  • *
  • {@link TestTemplateInvocationContextProvider}
  • *
  • {@link TestWatcher}
  • *
* * @since 5.0 * @see RegisterExtension * @see Extension */ @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Repeatable(Extensions.class) @API(status = STABLE, since = "5.0") public @interface ExtendWith { /** * An array of one or more {@link Extension} classes to register. */ Class[] value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/Extension.java000066400000000000000000000027631455764576500322610ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Marker interface for all extensions. * *

An {@code Extension} can be registered declaratively via * {@link ExtendWith @ExtendWith}, programmatically via * {@link RegisterExtension @RegisterExtension}, or automatically via * the {@link java.util.ServiceLoader} mechanism. For details on the latter, * consult the User Guide. * *

Constructor Requirements

* *

Extension implementations must have a default constructor if * registered via {@code @ExtendWith} or the {@code ServiceLoader}. When * registered via {@code @ExtendWith} the default constructor is not required * to be {@code public}. When registered via the {@code ServiceLoader} the * default constructor must be {@code public}. When registered via * {@code @RegisterExtension} the extension's constructors typically must be * {@code public} unless the extension provides {@code static} factory methods * or a builder API as an alternative to constructors. * * @since 5.0 */ @API(status = STABLE, since = "5.0") public interface Extension { } ExtensionConfigurationException.java000066400000000000000000000016651455764576500366110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered regarding the configuration of an * extension. * * @since 5.0 */ @API(status = STABLE, since = "5.0") public class ExtensionConfigurationException extends JUnitException { private static final long serialVersionUID = 1L; public ExtensionConfigurationException(String message) { super(message); } public ExtensionConfigurationException(String message, Throwable cause) { super(message, cause); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java000066400000000000000000000634021455764576500336230ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.Preconditions; /** * {@code ExtensionContext} encapsulates the context in which the * current test or container is being executed. * *

{@link Extension Extensions} are provided an instance of * {@code ExtensionContext} to perform their work. * * @since 5.0 * @see Store * @see Namespace */ @API(status = STABLE, since = "5.0") public interface ExtensionContext { /** * Get the parent extension context, if available. * * @return an {@code Optional} containing the parent; never {@code null} but * potentially empty * @see #getRoot() */ Optional getParent(); /** * Get the root {@code ExtensionContext}. * * @return the root extension context; never {@code null} but potentially * this {@code ExtensionContext} * @see #getParent() */ ExtensionContext getRoot(); /** * Get the unique ID of the current test or container. * * @return the unique ID of the test or container; never {@code null} or blank */ String getUniqueId(); /** * Get the display name for the current test or container. * *

The display name is either a default name or a custom name configured * via {@link org.junit.jupiter.api.DisplayName @DisplayName}. * *

For details on default display names consult the Javadoc for * {@link org.junit.jupiter.api.TestInfo#getDisplayName()}. * *

Note that display names are typically used for test reporting in IDEs * and build tools and may contain spaces, special characters, and even emoji. * * @return the display name of the test or container; never {@code null} or blank */ String getDisplayName(); /** * Get the set of all tags for the current test or container. * *

Tags may be declared directly on the test element or inherited * from an outer context. * * @return the set of tags for the test or container; never {@code null} but * potentially empty */ Set getTags(); /** * Get the {@link AnnotatedElement} corresponding to the current extension * context, if available. * *

For example, if the current extension context encapsulates a test * class, test method, test factory method, or test template method, the * annotated element will be the corresponding {@link Class} or {@link Method} * reference. * *

Favor this method over more specific methods whenever the * {@code AnnotatedElement} API suits the task at hand — for example, * when looking up annotations regardless of concrete element type. * * @return an {@code Optional} containing the {@code AnnotatedElement}; * never {@code null} but potentially empty * @see #getTestClass() * @see #getTestMethod() */ Optional getElement(); /** * Get the {@link Class} associated with the current test or container, * if available. * * @return an {@code Optional} containing the class; never {@code null} but * potentially empty * @see #getRequiredTestClass() */ Optional> getTestClass(); /** * Get the required {@link Class} associated with the current test * or container. * *

Use this method as an alternative to {@link #getTestClass()} for use * cases in which the test class is required to be present. * * @return the test class; never {@code null} * @throws PreconditionViolationException if the test class is not present * in this {@code ExtensionContext} */ default Class getRequiredTestClass() { return Preconditions.notNull(getTestClass().orElse(null), "Illegal state: required test class is not present in the current ExtensionContext"); } /** * Get the {@link Lifecycle} of the {@linkplain #getTestInstance() test * instance} associated with the current test or container, if available. * * @return an {@code Optional} containing the test instance {@code Lifecycle}; * never {@code null} but potentially empty * @since 5.1 * @see org.junit.jupiter.api.TestInstance {@code @TestInstance} */ @API(status = STABLE, since = "5.1") Optional getTestInstanceLifecycle(); /** * Get the test instance associated with the current test or container, * if available. * * @return an {@code Optional} containing the test instance; never * {@code null} but potentially empty * @see #getRequiredTestInstance() * @see #getTestInstances() */ Optional getTestInstance(); /** * Get the required test instance associated with the current test * or container. * *

Use this method as an alternative to {@link #getTestInstance()} for use * cases in which the test instance is required to be present. * * @return the test instance; never {@code null} * @throws PreconditionViolationException if the test instance is not present * in this {@code ExtensionContext} * * @see #getRequiredTestInstances() */ default Object getRequiredTestInstance() { return Preconditions.notNull(getTestInstance().orElse(null), "Illegal state: required test instance is not present in the current ExtensionContext"); } /** * Get the test instances associated with the current test or container, * if available. * *

While top-level tests only have a single test instance, nested tests * have one additional instance for each enclosing test class. * * @return an {@code Optional} containing the test instances; never * {@code null} but potentially empty * @since 5.4 * @see #getRequiredTestInstances() */ @API(status = STABLE, since = "5.7") Optional getTestInstances(); /** * Get the required test instances associated with the current test * or container. * *

Use this method as an alternative to {@link #getTestInstances()} for use * cases in which the test instances are required to be present. * * @return the test instances; never {@code null} * @throws PreconditionViolationException if the test instances are not present * in this {@code ExtensionContext} * @since 5.4 */ @API(status = STABLE, since = "5.7") default TestInstances getRequiredTestInstances() { return Preconditions.notNull(getTestInstances().orElse(null), "Illegal state: required test instances are not present in the current ExtensionContext"); } /** * Get the {@link Method} associated with the current test, if available. * * @return an {@code Optional} containing the method; never {@code null} but * potentially empty * @see #getRequiredTestMethod() */ Optional getTestMethod(); /** * Get the required {@link Method} associated with the current test * or container. * *

Use this method as an alternative to {@link #getTestMethod()} for use * cases in which the test method is required to be present. * * @return the test method; never {@code null} * @throws PreconditionViolationException if the test method is not present * in this {@code ExtensionContext} */ default Method getRequiredTestMethod() { return Preconditions.notNull(getTestMethod().orElse(null), "Illegal state: required test method is not present in the current ExtensionContext"); } /** * Get the exception that was thrown during execution of the test or container * associated with this {@code ExtensionContext}, if available. * *

This method is typically used for logging and tracing purposes. If you * wish to actually handle an exception thrown during test execution, * implement the {@link TestExecutionExceptionHandler} API. * *

Unlike the exception passed to a {@code TestExecutionExceptionHandler}, * an execution exception returned by this method can be any * exception thrown during the invocation of a {@code @Test} method, its * surrounding {@code @BeforeEach} and {@code @AfterEach} methods, or a * test-level {@link Extension}. Similarly, if this {@code ExtensionContext} * represents a test class, the execution exception returned by * this method can be any exception thrown in a {@code @BeforeAll} or * {@code AfterAll} method or a class-level {@link Extension}. * *

Note, however, that this method will never return an exception * swallowed by a {@code TestExecutionExceptionHandler}. Furthermore, if * multiple exceptions have been thrown during test execution, the exception * returned by this method will be the first such exception with all * additional exceptions {@linkplain Throwable#addSuppressed(Throwable) * suppressed} in the first one. * * @return an {@code Optional} containing the exception thrown; never * {@code null} but potentially empty if test execution has not (yet) * resulted in an exception */ Optional getExecutionException(); /** * Get the configuration parameter stored under the specified {@code key}. * *

If no such key is present in the {@code ConfigurationParameters} for * the JUnit Platform, an attempt will be made to look up the value as a * JVM system property. If no such system property exists, an attempt will * be made to look up the value in the JUnit Platform properties file. * * @param key the key to look up; never {@code null} or blank * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @since 5.1 * @see System#getProperty(String) * @see org.junit.platform.engine.ConfigurationParameters */ @API(status = STABLE, since = "5.1") Optional getConfigurationParameter(String key); /** * Get and transform the configuration parameter stored under the specified * {@code key} using the specified {@code transformer}. * *

If no such key is present in the {@code ConfigurationParameters} for * the JUnit Platform, an attempt will be made to look up the value as a * JVM system property. If no such system property exists, an attempt will * be made to look up the value in the JUnit Platform properties file. * *

In case the transformer throws an exception, it will be wrapped in a * {@link org.junit.platform.commons.JUnitException} with a helpful message. * * @param key the key to look up; never {@code null} or blank * @param transformer the transformer to apply in case a value is found; * never {@code null} * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @since 5.7 * @see System#getProperty(String) * @see org.junit.platform.engine.ConfigurationParameters */ @API(status = STABLE, since = "5.10") Optional getConfigurationParameter(String key, Function transformer); /** * Publish a map of key-value pairs to be consumed by an * {@code org.junit.platform.engine.EngineExecutionListener} in order to * supply additional information to the reporting infrastructure. * * @param map the key-value pairs to be published; never {@code null}; * keys and values within entries in the map also must not be * {@code null} or blank * @see #publishReportEntry(String, String) * @see #publishReportEntry(String) * @see org.junit.platform.engine.EngineExecutionListener#reportingEntryPublished */ void publishReportEntry(Map map); /** * Publish the specified key-value pair to be consumed by an * {@code org.junit.platform.engine.EngineExecutionListener} in order to * supply additional information to the reporting infrastructure. * * @param key the key of the published pair; never {@code null} or blank * @param value the value of the published pair; never {@code null} or blank * @see #publishReportEntry(Map) * @see #publishReportEntry(String) * @see org.junit.platform.engine.EngineExecutionListener#reportingEntryPublished */ default void publishReportEntry(String key, String value) { this.publishReportEntry(Collections.singletonMap(key, value)); } /** * Publish the specified value to be consumed by an * {@code org.junit.platform.engine.EngineExecutionListener} in order to * supply additional information to the reporting infrastructure. * *

This method delegates to {@link #publishReportEntry(String, String)}, * supplying {@code "value"} as the key and the supplied {@code value} * argument as the value. * * @param value the value to be published; never {@code null} or blank * @since 5.3 * @see #publishReportEntry(Map) * @see #publishReportEntry(String, String) * @see org.junit.platform.engine.EngineExecutionListener#reportingEntryPublished */ @API(status = STABLE, since = "5.3") default void publishReportEntry(String value) { this.publishReportEntry("value", value); } /** * Get the {@link Store} for the supplied {@link Namespace}. * *

Use {@code getStore(Namespace.GLOBAL)} to get the default, global {@link Namespace}. * *

A store is bound to its extension context lifecycle. When an extension * context lifecycle ends it closes its associated store. All stored values * that are instances of {@link ExtensionContext.Store.CloseableResource} are * notified by invoking their {@code close()} methods. * * @param namespace the {@code Namespace} to get the store for; never {@code null} * @return the store in which to put and get objects for other invocations * working in the same namespace; never {@code null} * @see Namespace#GLOBAL */ Store getStore(Namespace namespace); /** * Get the {@link ExecutionMode} associated with the current test or container. * * @return the {@code ExecutionMode} of the test; never {@code null} * * @since 5.8.1 * @see org.junit.jupiter.api.parallel.ExecutionMode {@code @ExecutionMode} */ @API(status = STABLE, since = "5.8.1") ExecutionMode getExecutionMode(); /** * Get an {@link ExecutableInvoker} to invoke methods and constructors * with support for dynamic resolution of parameters. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") ExecutableInvoker getExecutableInvoker(); /** * {@code Store} provides methods for extensions to save and retrieve data. */ interface Store { /** * Classes implementing this interface indicate that they want to {@link #close} * some underlying resource or resources when the enclosing {@link Store Store} * is closed. * *

Note that the {@code CloseableResource} API is only honored for * objects stored within an extension context {@link Store Store}. * *

The resources stored in a {@link Store Store} are closed in the * inverse order they were added in. * * @since 5.1 */ @API(status = STABLE, since = "5.1") interface CloseableResource { /** * Close underlying resources. * * @throws Throwable any throwable will be caught and rethrown */ void close() throws Throwable; } /** * Get the value that is stored under the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. * *

For greater type safety, consider using {@link #get(Object, Class)} * instead. * * @param key the key; never {@code null} * @return the value; potentially {@code null} * @see #get(Object, Class) * @see #getOrDefault(Object, Class, Object) */ Object get(Object key); /** * Get the value of the specified required type that is stored under * the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. * * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param the value type * @return the value; potentially {@code null} * @see #get(Object) * @see #getOrDefault(Object, Class, Object) */ V get(Object key, Class requiredType); /** * Get the value of the specified required type that is stored under * the supplied {@code key}, or the supplied {@code defaultValue} if no * value is found for the supplied {@code key} in this store or in an * ancestor. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. * * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param defaultValue the default value * @param the value type * @return the value; potentially {@code null} * @since 5.5 * @see #get(Object, Class) */ @API(status = STABLE, since = "5.5") default V getOrDefault(Object key, Class requiredType, V defaultValue) { V value = get(key, requiredType); return (value != null ? value : defaultValue); } /** * Get the object of type {@code type} that is present in this * {@code Store} (keyed by {@code type}); and otherwise invoke * the default constructor for {@code type} to generate the object, * store it, and return it. * *

This method is a shortcut for the following, where {@code X} is * the type of object we wish to retrieve from the store. * *

		 * X x = store.getOrComputeIfAbsent(X.class, key -> new X(), X.class);
		 * // Equivalent to:
		 * // X x = store.getOrComputeIfAbsent(X.class);
		 * 
* *

See {@link #getOrComputeIfAbsent(Object, Function, Class)} for * further details. * *

If {@code type} implements {@link ExtensionContext.Store.CloseableResource} * the {@code close()} method will be invoked on the stored object when * the store is closed. * * @param type the type of object to retrieve; never {@code null} * @param the key and value type * @return the object; never {@code null} * @since 5.1 * @see #getOrComputeIfAbsent(Object, Function) * @see #getOrComputeIfAbsent(Object, Function, Class) * @see CloseableResource */ @API(status = STABLE, since = "5.1") default V getOrComputeIfAbsent(Class type) { return getOrComputeIfAbsent(type, ReflectionSupport::newInstance, type); } /** * Get the value that is stored under the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. If no value is found for the supplied {@code key}, * a new value will be computed by the {@code defaultCreator} (given * the {@code key} as input), stored, and returned. * *

For greater type safety, consider using * {@link #getOrComputeIfAbsent(Object, Function, Class)} instead. * *

If the created value is an instance of {@link ExtensionContext.Store.CloseableResource} * the {@code close()} method will be invoked on the stored object when * the store is closed. * * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} but may return {@code null} * @param the key type * @param the value type * @return the value; potentially {@code null} * @see #getOrComputeIfAbsent(Class) * @see #getOrComputeIfAbsent(Object, Function, Class) * @see CloseableResource */ Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the * supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. If no value is found for the supplied {@code key}, * a new value will be computed by the {@code defaultCreator} (given * the {@code key} as input), stored, and returned. * *

If {@code requiredType} implements {@link ExtensionContext.Store.CloseableResource} * the {@code close()} method will be invoked on the stored object when * the store is closed. * * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} but may return {@code null} * @param requiredType the required type of the value; never {@code null} * @param the key type * @param the value type * @return the value; potentially {@code null} * @see #getOrComputeIfAbsent(Class) * @see #getOrComputeIfAbsent(Object, Function) * @see CloseableResource */ V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. * *

A stored {@code value} is visible in child {@link ExtensionContext * ExtensionContexts} for the store's {@code Namespace} unless they * overwrite it. * *

If the {@code value} is an instance of {@link ExtensionContext.Store.CloseableResource} * the {@code close()} method will be invoked on the stored object when * the store is closed. * * @param key the key under which the value should be stored; never * {@code null} * @param value the value to store; may be {@code null} * @see CloseableResource */ void put(Object key, Object value); /** * Remove the value that was previously stored under the supplied {@code key}. * *

The value will only be removed in the current {@link ExtensionContext}, * not in ancestors. In addition, the {@link CloseableResource} API will not * be honored for values that are manually removed via this method. * *

For greater type safety, consider using {@link #remove(Object, Class)} * instead. * * @param key the key; never {@code null} * @return the previous value or {@code null} if no value was present * for the specified key * @see #remove(Object, Class) */ Object remove(Object key); /** * Remove the value of the specified required type that was previously stored * under the supplied {@code key}. * *

The value will only be removed in the current {@link ExtensionContext}, * not in ancestors. In addition, the {@link CloseableResource} API will not * be honored for values that are manually removed via this method. * * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param the value type * @return the previous value or {@code null} if no value was present * for the specified key * @see #remove(Object) */ V remove(Object key, Class requiredType); } /** * A {@code Namespace} is used to provide a scope for data saved by * extensions within a {@link Store}. * *

Storing data in custom namespaces allows extensions to avoid accidentally * mixing data between extensions or across different invocations within the * lifecycle of a single extension. */ class Namespace { /** * The default, global namespace which allows access to stored data from * all extensions. */ public static final Namespace GLOBAL = Namespace.create(new Object()); /** * Create a namespace which restricts access to data to all extensions * which use the same sequence of {@code parts} for creating a namespace. * *

The order of the {@code parts} is significant. * *

Internally the {@code parts} are compared using {@link Object#equals(Object)}. */ public static Namespace create(Object... parts) { Preconditions.notEmpty(parts, "parts array must not be null or empty"); Preconditions.containsNoNullElements(parts, "individual parts must not be null"); return new Namespace(new ArrayList<>(Arrays.asList(parts))); } private final List parts; private Namespace(List parts) { this.parts = parts; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Namespace that = (Namespace) o; return this.parts.equals(that.parts); } @Override public int hashCode() { return this.parts.hashCode(); } /** * Create a new namespace by appending the supplied {@code parts} to the * existing sequence of parts in this namespace. * * @return new namespace; never {@code null} * @since 5.8 */ @API(status = STABLE, since = "5.10") public Namespace append(Object... parts) { Preconditions.notEmpty(parts, "parts array must not be null or empty"); Preconditions.containsNoNullElements(parts, "individual parts must not be null"); ArrayList newParts = new ArrayList<>(this.parts.size() + parts.length); newParts.addAll(this.parts); Collections.addAll(newParts, parts); return new Namespace(newParts); } } } ExtensionContextException.java000066400000000000000000000021751455764576500354230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered regarding the use of an * {@link ExtensionContext} or {@link Store}. * * @since 5.0 */ @API(status = STABLE, since = "5.0") public class ExtensionContextException extends JUnitException { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") public ExtensionContextException(String message) { super(message); } @API(status = EXPERIMENTAL, since = "5.10") public ExtensionContextException(String message, Throwable cause) { super(message, cause); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/Extensions.java000066400000000000000000000025011455764576500324320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Extensions} is a container for one or more {@code @ExtendWith} * declarations. * *

Note, however, that use of the {@code @Extensions} container is completely * optional since {@code @ExtendWith} is a {@linkplain java.lang.annotation.Repeatable * repeatable} annotation. * * @since 5.0 * @see ExtendWith * @see java.lang.annotation.Repeatable */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @API(status = STABLE, since = "5.0") public @interface Extensions { /** * An array of one or more {@link ExtendWith @ExtendWith} declarations. */ ExtendWith[] value(); } InvocationInterceptor.java000066400000000000000000000221031455764576500345440ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.apiguardian.api.API; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; /** * {@code InvocationInterceptor} defines the API for {@link Extension * Extensions} that wish to intercept calls to test code. * *

Invocation Contract

* *

Each method in this class must call {@link Invocation#proceed()} or {@link * Invocation#skip()} exactly once on the supplied invocation. Otherwise, the * enclosing test or container will be reported as failed. * *

The default implementation calls {@link Invocation#proceed() * proceed()} on the supplied {@linkplain Invocation invocation}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.5 * @see Invocation * @see ReflectiveInvocationContext * @see ExtensionContext */ @API(status = STABLE, since = "5.10") public interface InvocationInterceptor extends Extension { /** * Intercept the invocation of a test class constructor. * *

Note that the test class may not have been initialized * (static initialization) when this method is invoked. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @param the result type * @return the result of the invocation; never {@code null} * @throws Throwable in case of failure */ default T interceptTestClassConstructor(Invocation invocation, ReflectiveInvocationContext> invocationContext, ExtensionContext extensionContext) throws Throwable { return invocation.proceed(); } /** * Intercept the invocation of a {@link BeforeAll @BeforeAll} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptBeforeAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of a {@link BeforeEach @BeforeEach} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptBeforeEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of a {@link Test @Test} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of a {@link TestFactory @TestFactory} method, * such as a {@link org.junit.jupiter.api.RepeatedTest @RepeatedTest} or * {@code @ParameterizedTest} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @param the result type * @return the result of the invocation; potentially {@code null} * @throws Throwable in case of failures */ default T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { return invocation.proceed(); } /** * Intercept the invocation of a {@link TestTemplate @TestTemplate} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptTestTemplateMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of a {@link DynamicTest}. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures * @deprecated use {@link #interceptDynamicTest(Invocation, DynamicTestInvocationContext, ExtensionContext)} instead */ @Deprecated @API(status = DEPRECATED, since = "5.8") default void interceptDynamicTest(Invocation invocation, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of a {@link DynamicTest}. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ @API(status = EXPERIMENTAL, since = "5.8") default void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { // by default call the old interceptDynamicTest(Invocation, ExtensionContext) method so that existing extensions still work interceptDynamicTest(invocation, extensionContext); } /** * Intercept the invocation of an {@link AfterEach @AfterEach} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptAfterEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * Intercept the invocation of an {@link AfterAll @AfterAll} method. * * @param invocation the invocation that is being intercepted; never * {@code null} * @param invocationContext the context of the invocation that is being * intercepted; never {@code null} * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ default void interceptAfterAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } /** * An invocation that returns a result and may throw a {@link Throwable}. * *

This interface is not intended to be implemented by clients. * * @param the result type * @since 5.5 */ @API(status = STABLE, since = "5.10") interface Invocation { /** * Proceed with this invocation. * * @return the result of this invocation; potentially {@code null}. * @throws Throwable in case the invocation failed */ T proceed() throws Throwable; /** * Explicitly skip this invocation. * *

This allows to bypass the check that {@link #proceed()} must be * called at least once. The default implementation does nothing. */ @API(status = STABLE, since = "5.10") default void skip() { // do nothing } } } LifecycleMethodExecutionExceptionHandler.java000066400000000000000000000107321455764576500403220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code LifecycleMethodExecutionExceptionHandler} defines the API for * {@link Extension Extensions} that wish to handle exceptions thrown during * the execution of {@code @BeforeAll}, {@code @BeforeEach}, {@code @AfterEach}, * and {@code @AfterAll} lifecycle methods. * *

Common use cases include swallowing an exception if it's anticipated, * logging errors, or rolling back a transaction in certain error scenarios. * *

Implementations of this extension API must be registered at the class level * if exceptions thrown from {@code @BeforeAll} or {@code @AfterAll} methods are * to be handled. When registered at the test level, only exceptions thrown from * {@code @BeforeEach} or {@code @AfterEach} methods will be handled. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on constructor * requirements. * *

Implementation Guidelines

* *

An implementation of an exception handler method defined in this API must * perform one of the following. * *

    *
  1. Rethrow the supplied {@code Throwable} as is, which is the default implementation.
  2. *
  3. Swallow the supplied {@code Throwable}, thereby preventing propagation.
  4. *
  5. Throw a new exception, potentially wrapping the supplied {@code Throwable}.
  6. *
* *

If the supplied {@code Throwable} is swallowed by a handler method, subsequent * handler methods for the same lifecycle will not be invoked; otherwise, the * corresponding handler method of the next registered * {@code LifecycleMethodExecutionExceptionHandler} (if there is one) will be * invoked with any {@link Throwable} thrown by the previous handler. * * @since 5.5 * @see TestExecutionExceptionHandler */ @API(status = STABLE, since = "5.10") public interface LifecycleMethodExecutionExceptionHandler extends Extension { /** * Handle the supplied {@link Throwable} that was thrown during execution of * a {@code @BeforeAll} lifecycle method. * *

Please refer to the class-level Javadoc for * Implementation Guidelines. * * @param context the current extension context; never {@code null} * @param throwable the {@code Throwable} to handle; never {@code null} */ default void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { throw throwable; } /** * Handle the supplied {@link Throwable} that was thrown during execution of * a {@code @BeforeEach} lifecycle method. * *

Please refer to the class-level Javadoc for * Implementation Guidelines. * * @param context the current extension context; never {@code null} * @param throwable the {@code Throwable} to handle; never {@code null} */ default void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { throw throwable; } /** * Handle the supplied {@link Throwable} that was thrown during execution of * a {@code @AfterEach} lifecycle method. * *

Please refer to the class-level Javadoc for * Implementation Guidelines. * * @param context the current extension context; never {@code null} * @param throwable the {@code Throwable} to handle; never {@code null} */ default void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { throw throwable; } /** * Handle the supplied {@link Throwable} that was thrown during execution of * a {@code @AfterAll} lifecycle method. * *

Please refer to the class-level Javadoc for * Implementation Guidelines. * * @param context the current extension context; never {@code null} * @param throwable the {@code Throwable} to handle; never {@code null} */ default void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { throw throwable; } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java000066400000000000000000000075121455764576500335670ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Executable; import java.lang.reflect.Parameter; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code ParameterContext} encapsulates the context in which an * {@link #getDeclaringExecutable Executable} will be invoked for a given * {@link #getParameter Parameter}. * *

A {@code ParameterContext} is used to support parameter resolution via * a {@link ParameterResolver}. * * @since 5.0 * @see ParameterResolver * @see java.lang.reflect.Parameter * @see java.lang.reflect.Executable * @see java.lang.reflect.Method * @see java.lang.reflect.Constructor */ @API(status = STABLE, since = "5.0") public interface ParameterContext extends AnnotatedElementContext { /** * Get the {@link Parameter} for this context. * *

WARNING

*

When searching for annotations on the parameter in this context, * favor {@link #isAnnotated(Class)}, {@link #findAnnotation(Class)}, and * {@link #findRepeatableAnnotations(Class)} over methods in the * {@link Parameter} API due to a bug in {@code javac} on JDK versions prior * to JDK 9. * * @return the parameter; never {@code null} * @see #getIndex() */ Parameter getParameter(); /** * Get the index of the {@link Parameter} for this context within the * parameter list of the {@link #getDeclaringExecutable Executable} that * declares the parameter. * * @return the index of the parameter * @see #getParameter() * @see Executable#getParameters() */ int getIndex(); /** * Get the {@link Executable} (i.e., the {@link java.lang.reflect.Method} or * {@link java.lang.reflect.Constructor}) that declares the {@code Parameter} * for this context. * * @return the declaring {@code Executable}; never {@code null} * @see Parameter#getDeclaringExecutable() */ default Executable getDeclaringExecutable() { return getParameter().getDeclaringExecutable(); } /** * Get the target on which the {@link #getDeclaringExecutable Executable} * that declares the {@link #getParameter Parameter} for this context will * be invoked, if available. * * @return an {@link Optional} containing the target on which the * {@code Executable} will be invoked; never {@code null} but will be * empty if the {@code Executable} is a constructor or a * {@code static} method. */ Optional getTarget(); /** * {@inheritDoc} * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") @Override default AnnotatedElement getAnnotatedElement() { return getParameter(); } /** * {@inheritDoc} * @since 5.1.1 */ @API(status = STABLE, since = "5.10") @Override default boolean isAnnotated(Class annotationType) { return AnnotatedElementContext.super.isAnnotated(annotationType); } /** * {@inheritDoc} * @since 5.1.1 */ @API(status = STABLE, since = "5.10") @Override default Optional findAnnotation(Class annotationType) { return AnnotatedElementContext.super.findAnnotation(annotationType); } /** * {@inheritDoc} * @since 5.1.1 */ @API(status = STABLE, since = "5.10") @Override default List findRepeatableAnnotations(Class annotationType) { return AnnotatedElementContext.super.findRepeatableAnnotations(annotationType); } } ParameterResolutionException.java000066400000000000000000000017331455764576500361050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered in the configuration or execution of a * {@link ParameterResolver}. * * @since 5.0 * @see ParameterResolver */ @API(status = STABLE, since = "5.0") public class ParameterResolutionException extends JUnitException { private static final long serialVersionUID = 1L; public ParameterResolutionException(String message) { super(message); } public ParameterResolutionException(String message, Throwable cause) { super(message, cause); } } ParameterResolver.java000066400000000000000000000070651455764576500336700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Parameter; import org.apiguardian.api.API; /** * {@code ParameterResolver} defines the API for {@link Extension Extensions} * that wish to dynamically resolve arguments for {@linkplain Parameter parameters} * at runtime. * *

If a constructor for a test class or a * {@link org.junit.jupiter.api.Test @Test}, * {@link org.junit.jupiter.api.BeforeEach @BeforeEach}, * {@link org.junit.jupiter.api.AfterEach @AfterEach}, * {@link org.junit.jupiter.api.BeforeAll @BeforeAll}, or * {@link org.junit.jupiter.api.AfterAll @AfterAll} method declares a parameter, * an argument for the parameter must be resolved at runtime by a * {@code ParameterResolver}. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.0 * @see #supportsParameter(ParameterContext, ExtensionContext) * @see #resolveParameter(ParameterContext, ExtensionContext) * @see ParameterContext * @see TestInstanceFactory * @see TestInstancePostProcessor * @see TestInstancePreDestroyCallback */ @API(status = STABLE, since = "5.0") public interface ParameterResolver extends Extension { /** * Determine if this resolver supports resolution of an argument for the * {@link Parameter} in the supplied {@link ParameterContext} for the supplied * {@link ExtensionContext}. * *

The {@link java.lang.reflect.Method} or {@link java.lang.reflect.Constructor} * in which the parameter is declared can be retrieved via * {@link ParameterContext#getDeclaringExecutable()}. * * @param parameterContext the context for the parameter for which an argument should * be resolved; never {@code null} * @param extensionContext the extension context for the {@code Executable} * about to be invoked; never {@code null} * @return {@code true} if this resolver can resolve an argument for the parameter * @see #resolveParameter * @see ParameterContext */ boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException; /** * Resolve an argument for the {@link Parameter} in the supplied {@link ParameterContext} * for the supplied {@link ExtensionContext}. * *

This method is only called by the framework if {@link #supportsParameter} * previously returned {@code true} for the same {@link ParameterContext} * and {@link ExtensionContext}. * *

The {@link java.lang.reflect.Method} or {@link java.lang.reflect.Constructor} * in which the parameter is declared can be retrieved via * {@link ParameterContext#getDeclaringExecutable()}. * * @param parameterContext the context for the parameter for which an argument should * be resolved; never {@code null} * @param extensionContext the extension context for the {@code Executable} * about to be invoked; never {@code null} * @return the resolved argument for the parameter; may only be {@code null} if the * parameter type is not a primitive * @see #supportsParameter * @see ParameterContext */ Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException; } ReflectiveInvocationContext.java000066400000000000000000000043671455764576500357170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Executable; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code ReflectiveInvocationContext} encapsulates the context of * a reflective invocation of an executable (method or constructor). * *

This interface is not intended to be implemented by clients. * * @since 5.5 */ @API(status = STABLE, since = "5.10") public interface ReflectiveInvocationContext { /** * Get the target class of this invocation context. * *

If this invocation context represents an instance method, this * method returns the class of the object the method will be invoked on, * not the class it is declared in. Otherwise, if this invocation * represents a static method or constructor, this method returns the * class the method or constructor is declared in. * * @return the target class of this invocation context; never * {@code null} */ Class getTargetClass(); /** * Get the method or constructor of this invocation context. * * @return the executable of this invocation context; never {@code null} */ T getExecutable(); /** * Get the arguments of the executable in this invocation context. * * @return the arguments of the executable in this invocation context; * immutable and never {@code null} */ List getArguments(); /** * Get the target object of this invocation context, if available. * *

If this invocation context represents an instance method, this * method returns the object the method will be invoked on. Otherwise, * if this invocation context represents a static method or * constructor, this method returns {@link Optional#empty() empty()}. * * @return the target of the executable of this invocation context; never * {@code null} but potentially empty */ Optional getTarget(); } RegisterExtension.java000066400000000000000000000141331455764576500337010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @RegisterExtension} is used to register an {@link Extension} via a * field in a test class. * *

In contrast to {@link ExtendWith @ExtendWith} which is used to register * extensions declaratively, {@code @RegisterExtension} can be used to * register an extension programmatically — for example, in order * to pass arguments to the extension's constructor, {@code static} factory * method, or builder API. * *

{@code @RegisterExtension} fields must not be {@code null} (when evaluated) * but may be either {@code static} or non-static. * *

Static Fields

* *

If a {@code @RegisterExtension} field is {@code static}, the extension * will be registered after extensions that are registered at the class level * via {@code @ExtendWith}. Such static extensions are not limited in * which extension APIs they can implement. Extensions registered via static * fields may therefore implement class-level and instance-level extension APIs * such as {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link TestInstanceFactory}, {@link TestInstancePostProcessor} and * {@link TestInstancePreDestroyCallback} as well as method-level extension APIs * such as {@link BeforeEachCallback}, etc. * *

Instance Fields

* *

If a {@code @RegisterExtension} field is non-static (i.e., an instance * field), the extension will be registered after the test class has been * instantiated and after all {@link TestInstancePostProcessor * TestInstancePostProcessors} have been given a chance to post-process the * test instance (potentially injecting the instance of the extension to be * used into the annotated field). Thus, if such an instance extension * implements class-level or instance-level extension APIs such as * {@link BeforeAllCallback}, {@link AfterAllCallback}, * {@link TestInstanceFactory}, or {@link TestInstancePostProcessor} those APIs * will not be honored. By default, an instance extension will be registered * after extensions that are registered at the method level via * {@code @ExtendWith}; however, if the test class is configured with * {@link org.junit.jupiter.api.TestInstance.Lifecycle @TestInstance(Lifecycle.PER_CLASS)} * semantics, an instance extension will be registered before extensions * that are registered at the method level via {@code @ExtendWith}. * *

Inheritance

* *

{@code @RegisterExtension} fields are inherited from superclasses as long * as they are not hidden or overridden. Furthermore, * {@code @RegisterExtension} fields from superclasses will be registered before * {@code @RegisterExtension} fields in subclasses. * *

Registration Order

* *

By default, if multiple extensions are registered via * {@code @RegisterExtension}, they will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute extensions in the same order, thereby allowing for * repeatable builds. However, there are times when extensions need to be * registered in an explicit order. To achieve that, you can annotate * {@code @RegisterExtension} fields with {@link org.junit.jupiter.api.Order @Order}. * Any {@code @RegisterExtension} field not annotated with {@code @Order} will be * ordered using the {@link org.junit.jupiter.api.Order#DEFAULT default} order * value. Note that {@code @ExtendWith} fields can also be ordered with * {@code @Order}, relative to {@code @RegisterExtension} fields and other * {@code @ExtendWith} fields. * *

Example Usage

* *

In the following example, the {@code docs} field in the test class is * initialized programmatically by supplying a custom {@code lookUpDocsDir()} * method to a {@code static} factory method in the {@code DocumentationExtension}. * The configured {@code DocumentationExtension} will be automatically registered * as an extension. In addition, test methods can access the instance of the * extension via the {@code docs} field if necessary. * *

 * class DocumentationTests {
 *
 *     static Path lookUpDocsDir() {
 *         // return path to docs dir
 *     }
 *
 *     {@literal @}RegisterExtension
 *     DocumentationExtension docs =
 *         DocumentationExtension.forPath(lookUpDocsDir());
 *
 *     {@literal @}Test
 *     void generateDocumentation() {
 *         // use docs ...
 *     }
 * }
* *

Supported Extension APIs

* *
    *
  • {@link ExecutionCondition}
  • *
  • {@link InvocationInterceptor}
  • *
  • {@link BeforeAllCallback}
  • *
  • {@link AfterAllCallback}
  • *
  • {@link BeforeEachCallback}
  • *
  • {@link AfterEachCallback}
  • *
  • {@link BeforeTestExecutionCallback}
  • *
  • {@link AfterTestExecutionCallback}
  • *
  • {@link TestInstanceFactory}
  • *
  • {@link TestInstancePostProcessor}
  • *
  • {@link TestInstancePreConstructCallback}
  • *
  • {@link TestInstancePreDestroyCallback}
  • *
  • {@link ParameterResolver}
  • *
  • {@link LifecycleMethodExecutionExceptionHandler}
  • *
  • {@link TestExecutionExceptionHandler}
  • *
  • {@link TestTemplateInvocationContextProvider}
  • *
  • {@link TestWatcher}
  • *
* * @since 5.1 * @see ExtendWith @ExtendWith * @see Extension * @see org.junit.jupiter.api.Order @Order */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.1") public @interface RegisterExtension { } TestExecutionExceptionHandler.java000066400000000000000000000046031455764576500362010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code TestExecutionExceptionHandler} defines the API for {@link Extension * Extensions} that wish to handle exceptions thrown during test execution. * *

In this context, test execution refers to the physical * invocation of a {@code @Test} method and not to any test-level extensions * or callbacks. * *

Common use cases include swallowing an exception if it's anticipated * or rolling back a transaction in certain error scenarios. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.0 * @see LifecycleMethodExecutionExceptionHandler */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface TestExecutionExceptionHandler extends Extension { /** * Handle the supplied {@link Throwable throwable}. * *

Implementors must perform one of the following. *

    *
  1. Swallow the supplied {@code throwable}, thereby preventing propagation.
  2. *
  3. Rethrow the supplied {@code throwable} as is.
  4. *
  5. Throw a new exception, potentially wrapping the supplied {@code throwable}.
  6. *
* *

If the supplied {@code throwable} is swallowed, subsequent * {@code TestExecutionExceptionHandlers} will not be invoked; otherwise, * the next registered {@code TestExecutionExceptionHandler} (if there is * one) will be invoked with any {@link Throwable} thrown by this handler. * *

Note that the {@link ExtensionContext#getExecutionException() execution * exception} in the supplied {@code ExtensionContext} will not * contain the {@code Throwable} thrown during invocation of the corresponding * {@code @Test} method. * * @param context the current extension context; never {@code null} * @param throwable the {@code Throwable} to handle; never {@code null} */ void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable; } TestInstanceFactory.java000066400000000000000000000056471455764576500341660ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code TestInstanceFactory} defines the API for {@link Extension * Extensions} that wish to {@linkplain #createTestInstance create} test instances. * *

Common use cases include creating test instances with special construction * requirements or acquiring the test instance from a dependency injection * framework. * *

Extensions that implement {@code TestInstanceFactory} must be registered * at the class level. * *

Warning

* *

Only one {@code TestInstanceFactory} is allowed to be registered for any * given test class. Registering multiple factories for any single test class * will result in an exception being thrown for all tests in that class, in any * subclass, and in any nested class. Note that any {@code TestInstanceFactory} * registered in a {@linkplain Class#getSuperclass() superclass} or * {@linkplain Class#getEnclosingClass() enclosing} class (i.e., in the case of * a {@code @Nested} test class) is inherited. It is therefore the * user's responsibility to ensure that only a single {@code TestInstanceFactory} * is registered for any specific test class. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.3 * @see #createTestInstance(TestInstanceFactoryContext, ExtensionContext) * @see TestInstanceFactoryContext * @see TestInstancePostProcessor * @see TestInstancePreDestroyCallback * @see ParameterResolver */ @FunctionalInterface @API(status = STABLE, since = "5.7") public interface TestInstanceFactory extends Extension { /** * Callback for creating a test instance for the supplied context. * *

Note: the {@code ExtensionContext} supplied to a * {@code TestInstanceFactory} will always return an empty * {@link java.util.Optional} value from * {@link ExtensionContext#getTestInstance() getTestInstance()} since the * test instance cannot exist before it has been created by a * {@code TestInstanceFactory} or the framework itself. * * @param factoryContext the context for the test class to be instantiated; * never {@code null} * @param extensionContext the current extension context; never {@code null} * @return the test instance; never {@code null} * @throws TestInstantiationException if an error occurs while creating the * test instance */ Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) throws TestInstantiationException; } TestInstanceFactoryContext.java000066400000000000000000000025621455764576500355240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; /** * {@code TestInstanceFactoryContext} encapsulates the context in which * a {@linkplain #getTestClass test class} is to be instantiated by a * {@link TestInstanceFactory}. * * @since 5.3 * @see TestInstanceFactory */ @API(status = STABLE, since = "5.7") public interface TestInstanceFactoryContext { /** * Get the test class for this context. * * @return the test class to be instantiated; never {@code null} */ Class getTestClass(); /** * Get the instance of the outer class, if available. * *

The returned {@link Optional} will be empty unless the * current {@linkplain #getTestClass() test class} is a * {@link org.junit.jupiter.api.Nested @Nested} test class. * * @return an {@code Optional} containing the outer test instance; never * {@code null} but potentially empty * @see org.junit.jupiter.api.Nested */ Optional getOuterInstance(); } TestInstancePostProcessor.java000066400000000000000000000036611455764576500353760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code TestInstancePostProcessor} defines the API for {@link Extension * Extensions} that wish to post-process test instances. * *

Common use cases include injecting dependencies into the test * instance, invoking custom initialization methods on the test instance, * etc. * *

Extensions that implement {@code TestInstancePostProcessor} must be * registered at the class level. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.0 * @see #postProcessTestInstance(Object, ExtensionContext) * @see TestInstancePreDestroyCallback * @see TestInstanceFactory * @see ParameterResolver */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface TestInstancePostProcessor extends Extension { /** * Callback for post-processing the supplied test instance. * *

Note: the {@code ExtensionContext} supplied to a * {@code TestInstancePostProcessor} will always return an empty * {@link java.util.Optional} value from {@link ExtensionContext#getTestInstance() * getTestInstance()}. A {@code TestInstancePostProcessor} should therefore * only attempt to process the supplied {@code testInstance}. * * @param testInstance the instance to post-process; never {@code null} * @param context the current extension context; never {@code null} */ void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception; } TestInstancePreConstructCallback.java000066400000000000000000000042621455764576500366170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance.Lifecycle; /** * {@code TestInstancePreConstructCallback} defines the API for {@link Extension * Extensions} that wish to be invoked prior to creation of test instances. * *

This extension is a symmetric counterpart to {@link TestInstancePreDestroyCallback}. * The use cases for this extension may include preparing context-sensitive arguments * that are injected into the instance's constructor. * *

Extensions that implement {@code TestInstancePreConstructCallback} must be * registered at the class level if the test class is configured with * {@link Lifecycle @TestInstance(Lifecycle.PER_CLASS)} semantics. If the test * class is configured with * {@link Lifecycle @TestInstance(Lifecycle.PER_METHOD)} semantics, * {@code TestInstancePreConstructCallback} extensions may be registered at the * class level or at the method level. In the latter case, the extension will * only be applied to the test method for which it is registered. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on constructor * requirements. * * @since 5.9 * @see TestInstancePreDestroyCallback * @see TestInstanceFactory * @see ParameterResolver */ @FunctionalInterface @API(status = EXPERIMENTAL, since = "5.9") public interface TestInstancePreConstructCallback extends Extension { /** * Callback invoked prior to test instances being constructed. * * @param factoryContext the context for the test instance about to be instantiated; * never {@code null} * @param context the current extension context; never {@code null} */ void preConstructTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext context) throws Exception; } TestInstancePreDestroyCallback.java000066400000000000000000000116301455764576500362610ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import org.apiguardian.api.API; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.TestInstance.Lifecycle; /** * {@code TestInstancePreDestroyCallback} defines the API for {@link Extension * Extensions} that wish to process test instances after they have been * used in tests but before they are destroyed. * *

Common use cases include releasing resources that have been created for * the test instance, invoking custom clean-up methods on the test instance, etc. * *

Extensions that implement {@code TestInstancePreDestroyCallback} must be * registered at the class level if the test class is configured with * {@link Lifecycle @TestInstance(Lifecycle.PER_CLASS)} * semantics. If the test class is configured with * {@link Lifecycle @TestInstance(Lifecycle.PER_METHOD)} * semantics, {@code TestInstancePreDestroyCallback} extensions may be registered * at the class level or at the method level. In the latter case, the * {@code TestInstancePreDestroyCallback} extension will only be applied to the * test method for which it is registered. * *

A symmetric {@link TestInstancePreConstructCallback} extension defines a callback * hook that is invoked prior to any test class instances being constructed. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on constructor * requirements. * * @since 5.6 * @see #preDestroyTestInstance(ExtensionContext) * @see TestInstancePostProcessor * @see TestInstancePreConstructCallback * @see TestInstanceFactory * @see ParameterResolver */ @FunctionalInterface @API(status = STABLE, since = "5.7") public interface TestInstancePreDestroyCallback extends Extension { /** * Callback for processing test instances before they are destroyed. * *

Contrary to {@link TestInstancePostProcessor#postProcessTestInstance} * this method is only called once for each {@link ExtensionContext} even if * there are multiple test instances about to be destroyed in case of * {@link Nested @Nested} tests. Please use the provided * {@link #preDestroyTestInstances(ExtensionContext, Consumer)} utility * method to ensure that all test instances are handled. * * @param context the current extension context; never {@code null} * @see ExtensionContext#getTestInstance() * @see ExtensionContext#getRequiredTestInstance() * @see ExtensionContext#getTestInstances() * @see ExtensionContext#getRequiredTestInstances() * @see #preDestroyTestInstances(ExtensionContext, Consumer) */ void preDestroyTestInstance(ExtensionContext context) throws Exception; /** * Utility method for processing all test instances of an * {@link ExtensionContext} that are not present in any of its parent * contexts. * *

This method should be called in order to implement this interface * correctly since it ensures that the right test instances are processed * regardless of the used {@linkplain Lifecycle lifecycle}. The supplied * callback is called once per test instance that is about to be destroyed * starting with the innermost one. * *

This method is intended to be called from an implementation of * {@link #preDestroyTestInstance(ExtensionContext)} like this: * *

{@code class MyExtension implements TestInstancePreDestroyCallback {
	 *    @Override
	 *    public void preDestroyTestInstance(ExtensionContext context) {
	 *        TestInstancePreDestroyCallback.preDestroyTestInstances(context, testInstance -> {
	 *            // custom logic that processes testInstance
	 *        });
	 *    }
	 *}}
* * @param context the current extension context; never {@code null} * @param callback the callback to be invoked for every test instance of the * current extension context that is about to be destroyed; never * {@code null} * @since 5.7.1 */ @API(status = STABLE, since = "5.10") static void preDestroyTestInstances(ExtensionContext context, Consumer callback) { List destroyedInstances = new ArrayList<>(context.getRequiredTestInstances().getAllInstances()); for (Optional current = context.getParent(); current.isPresent(); current = current.get().getParent()) { current.get().getTestInstances().map(TestInstances::getAllInstances).ifPresent( destroyedInstances::removeAll); } Collections.reverse(destroyedInstances); destroyedInstances.forEach(callback); } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstances.java000066400000000000000000000036471455764576500330760ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * {@code TestInstances} encapsulates the test instances of a test. * *

While top-level tests only have a single test instance, nested tests * have one additional instance for each enclosing test class. * * @since 5.4 * @see ExtensionContext#getTestInstances() * @see ExtensionContext#getRequiredTestInstances() */ @API(status = STABLE, since = "5.7") public interface TestInstances { /** * Get the innermost test instance. * *

The innermost instance is the one closest to the test method. * * @return the innermost test instance; never {@code null} */ Object getInnermostInstance(); /** * Get the enclosing test instances, excluding the innermost test instance, * ordered from outermost to innermost. * * @return the enclosing test instances; never {@code null} or containing * {@code null}, but potentially empty */ List getEnclosingInstances(); /** * Get all test instances, ordered from outermost to innermost. * * @return all test instances; never {@code null}, containing {@code null}, * or empty */ List getAllInstances(); /** * Find the first test instance that is an instance of the supplied required * type, checking from innermost to outermost. * * @param requiredType the type to search for * @return the first test instance of the required type; never {@code null} * but potentially empty */ Optional findInstance(Class requiredType); } TestInstantiationException.java000066400000000000000000000016611455764576500355650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered during the execution of * a {@link TestInstanceFactory}. * * @since 5.3 */ @API(status = STABLE, since = "5.10") public class TestInstantiationException extends JUnitException { private static final long serialVersionUID = 1L; public TestInstantiationException(String message) { super(message); } public TestInstantiationException(String message, Throwable cause) { super(message, cause); } } TestTemplateInvocationContext.java000066400000000000000000000044531455764576500362360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import org.apiguardian.api.API; /** * {@code TestTemplateInvocationContext} represents the context of a * single invocation of a {@linkplain org.junit.jupiter.api.TestTemplate test * template}. * *

Each context is provided by a {@link TestTemplateInvocationContextProvider}. * * @since 5.0 * @see org.junit.jupiter.api.TestTemplate * @see TestTemplateInvocationContextProvider */ @API(status = STABLE, since = "5.0") public interface TestTemplateInvocationContext { /** * Get the display name for this invocation. * *

The supplied {@code invocationIndex} is incremented by the framework * with each test invocation. Thus, in the case of multiple active * {@linkplain TestTemplateInvocationContextProvider providers}, only the * first active provider receives indices starting with {@code 1}. * *

The default implementation returns the supplied {@code invocationIndex} * wrapped in brackets — for example, {@code [1]}, {@code [42]}, etc. * * @param invocationIndex the index of this invocation (1-based). * @return the display name for this invocation; never {@code null} or blank */ default String getDisplayName(int invocationIndex) { return "[" + invocationIndex + "]"; } /** * Get the additional {@linkplain Extension extensions} for this invocation. * *

The extensions provided by this method will only be used for this * invocation of the test template. Thus, it does not make sense to return * an extension that acts solely on the container level (e.g. * {@link BeforeAllCallback}). * *

The default implementation returns an empty list. * * @return the additional extensions for this invocation; never {@code null} * or containing {@code null} elements, but potentially empty */ default List getAdditionalExtensions() { return emptyList(); } } TestTemplateInvocationContextProvider.java000066400000000000000000000072441455764576500377520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.stream.Stream; import org.apiguardian.api.API; /** * {@code TestTemplateInvocationContextProvider} defines the API for * {@link Extension Extensions} that wish to provide one or multiple contexts * for the invocation of a * {@link org.junit.jupiter.api.TestTemplate @TestTemplate} method. * *

This extension point makes it possible to execute a test template in * different contexts — for example, with different parameters, by * preparing the test class instance differently, or multiple times without * modifying the context. * *

This interface defines two methods: {@link #supportsTestTemplate} and * {@link #provideTestTemplateInvocationContexts}. The former is called by the * framework to determine whether this extension wants to act on a test template * that is about to be executed. If so, the latter is called and must return a * {@link Stream} of {@link TestTemplateInvocationContext} instances. Otherwise, * this provider is ignored for the execution of the current test template. * *

A provider that has returned {@code true} from its {@link #supportsTestTemplate} * method is called active. When multiple providers are active for a * test template method, the {@code Streams} returned by their * {@link #provideTestTemplateInvocationContexts} methods will be chained, and * the test template method will be invoked using the contexts of all active * providers. * *

Constructor Requirements

* *

Consult the documentation in {@link Extension} for details on * constructor requirements. * * @since 5.0 * @see org.junit.jupiter.api.TestTemplate * @see TestTemplateInvocationContext */ @API(status = STABLE, since = "5.0") public interface TestTemplateInvocationContextProvider extends Extension { /** * Determine if this provider supports providing invocation contexts for the * test template method represented by the supplied {@code context}. * * @param context the extension context for the test template method about * to be invoked; never {@code null} * @return {@code true} if this provider can provide invocation contexts * @see #provideTestTemplateInvocationContexts * @see ExtensionContext */ boolean supportsTestTemplate(ExtensionContext context); /** * Provide {@linkplain TestTemplateInvocationContext invocation contexts} * for the test template method represented by the supplied {@code context}. * *

This method is only called by the framework if {@link #supportsTestTemplate} * previously returned {@code true} for the same {@link ExtensionContext}; * this method is allowed to return an empty {@code Stream} but not {@code null}. * *

The returned {@code Stream} will be properly closed by calling * {@link Stream#close()}, making it safe to use a resource such as * {@link java.nio.file.Files#lines(java.nio.file.Path) Files.lines()}. * * @param context the extension context for the test template method about * to be invoked; never {@code null} * @return a {@code Stream} of {@code TestTemplateInvocationContext} * instances for the invocation of the test template method; never {@code null} * @see #supportsTestTemplate * @see ExtensionContext */ Stream provideTestTemplateInvocationContexts(ExtensionContext context); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestWatcher.java000066400000000000000000000115241455764576500325350ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; /** * {@code TestWatcher} defines the API for {@link Extension Extensions} that * wish to process test results. * *

The methods in this API are called after a test has been skipped or * executed. Any {@link ExtensionContext.Store.CloseableResource CloseableResource} * objects stored in the {@link ExtensionContext.Store Store} of the supplied * {@link ExtensionContext} will have already been closed before * methods in this API are invoked. * *

Please note that this API is currently only used to report the results of * {@link org.junit.jupiter.api.Test @Test} methods and * {@link org.junit.jupiter.api.TestTemplate @TestTemplate} methods (e.g., * {@code @RepeatedTest} and {@code @ParameterizedTest}). Moreover, if there is a * failure at the class level — for example, an exception thrown by a * {@code @BeforeAll} method — no test results will be reported. Similarly, * if the test class is disabled via an {@link ExecutionCondition} — for * example, {@code @Disabled} — no test results will be reported. * *

Extensions implementing this interface can be registered at the class level, * instance level, or method level. When registered at the class level, a * {@code TestWatcher} will be invoked for any contained test method including * those in {@link org.junit.jupiter.api.Nested @Nested} classes. When registered * at the method level, a {@code TestWatcher} will only be invoked for the test * method for which it was registered. * *

WARNING: If a {@code TestWatcher} is registered via a * non-static (instance) field — for example, using * {@link RegisterExtension @RegisterExtension} — and the test class is * configured with * {@link org.junit.jupiter.api.TestInstance @TestInstance(Lifecycle.PER_METHOD)} * semantics (which is the default lifecycle mode), the {@code TestWatcher} will * not be invoked with events for {@code @TestTemplate} methods * (such as {@code @RepeatedTest} and {@code @ParameterizedTest}). To ensure that * a {@code TestWatcher} is invoked for all test methods in a given class, it is * therefore recommended that the {@code TestWatcher} be registered at the class * level with {@link ExtendWith @ExtendWith} or via a {@code static} field with * {@code @RegisterExtension} or {@code @ExtendWith}. * *

Exception Handling

* *

In contrast to other {@link Extension} APIs, a {@code TestWatcher} is not * permitted to adversely influence the execution of tests. Consequently, any * exception thrown by a method in the {@code TestWatcher} API will be logged at * {@code WARNING} level and will not be allowed to propagate or fail test * execution. * * @since 5.4 */ @API(status = STABLE, since = "5.7") public interface TestWatcher extends Extension { /** * Invoked after a disabled test has been skipped. * *

The default implementation does nothing. Concrete implementations can * override this method as appropriate. * * @param context the current extension context; never {@code null} * @param reason the reason the test is disabled; never {@code null} but * potentially empty */ default void testDisabled(ExtensionContext context, Optional reason) { /* no-op */ } /** * Invoked after a test has completed successfully. * *

The default implementation does nothing. Concrete implementations can * override this method as appropriate. * * @param context the current extension context; never {@code null} */ default void testSuccessful(ExtensionContext context) { /* no-op */ } /** * Invoked after a test has been aborted. * *

The default implementation does nothing. Concrete implementations can * override this method as appropriate. * * @param context the current extension context; never {@code null} * @param cause the throwable responsible for the test being aborted; may be {@code null} */ default void testAborted(ExtensionContext context, Throwable cause) { /* no-op */ } /** * Invoked after a test has failed. * *

The default implementation does nothing. Concrete implementations can * override this method as appropriate. * * @param context the current extension context; never {@code null} * @param cause the throwable that caused test failure; may be {@code null} */ default void testFailed(ExtensionContext context, Throwable cause) { /* no-op */ } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/package-info.java000066400000000000000000000001371455764576500326220ustar00rootroot00000000000000/** * JUnit Jupiter API for writing extensions. */ package org.junit.jupiter.api.extension; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/000077500000000000000000000000001455764576500311465ustar00rootroot00000000000000TypeBasedParameterResolver.java000066400000000000000000000055111455764576500371770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension.support; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.util.Preconditions; /** * {@link ParameterResolver} adapter which resolves a parameter based on its exact type. * * @param the type of the parameter supported by this {@code ParameterResolver} * @since 5.6 */ @API(status = STABLE, since = "5.10") public abstract class TypeBasedParameterResolver implements ParameterResolver { private final Type supportedParameterType; public TypeBasedParameterResolver() { this.supportedParameterType = enclosedTypeOfParameterResolver(); } @Override public final boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return this.supportedParameterType.equals(getParameterType(parameterContext)); } @Override public abstract T resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException; private Type getParameterType(ParameterContext parameterContext) { return parameterContext.getParameter().getParameterizedType(); } private Type enclosedTypeOfParameterResolver() { ParameterizedType typeBasedParameterResolverSuperclass = findTypeBasedParameterResolverSuperclass(getClass()); Preconditions.notNull(typeBasedParameterResolverSuperclass, () -> String.format( "Failed to discover parameter type supported by %s; " + "potentially caused by lacking parameterized type in class declaration.", getClass().getName())); return typeBasedParameterResolverSuperclass.getActualTypeArguments()[0]; } private ParameterizedType findTypeBasedParameterResolverSuperclass(Class clazz) { Class superclass = clazz.getSuperclass(); // Abort? if (superclass == null || superclass == Object.class) { return null; } Type genericSuperclass = clazz.getGenericSuperclass(); if (genericSuperclass instanceof ParameterizedType) { Type rawType = ((ParameterizedType) genericSuperclass).getRawType(); if (rawType == TypeBasedParameterResolver.class) { return (ParameterizedType) genericSuperclass; } } return findTypeBasedParameterResolverSuperclass(superclass); } } package-info.java000066400000000000000000000001571455764576500342610ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/** * JUnit Jupiter API support for writing extensions. */ package org.junit.jupiter.api.extension.support; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/000077500000000000000000000000001455764576500272435ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/Executable.java000066400000000000000000000035331455764576500321730ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.function; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code Executable} is a functional interface that can be used to * implement any generic block of code that potentially throws a * {@link Throwable}. * *

The {@code Executable} interface is similar to {@link java.lang.Runnable}, * except that an {@code Executable} can throw any kind of exception. * *

Rationale for throwing {@code Throwable} instead of {@code Exception}

* *

Although Java applications typically throw exceptions that are instances * of {@link java.lang.Exception}, {@link java.lang.RuntimeException}, * {@link java.lang.Error}, or {@link java.lang.AssertionError} (in testing * scenarios), there may be use cases where an {@code Executable} needs to * explicitly throw a {@code Throwable}. In order to support such specialized * use cases, {@link #execute()} is declared to throw {@code Throwable}. * * @since 5.0 * @see org.junit.jupiter.api.Assertions#assertAll(Executable...) * @see org.junit.jupiter.api.Assertions#assertAll(String, Executable...) * @see org.junit.jupiter.api.Assertions#assertThrows(Class, Executable) * @see org.junit.jupiter.api.Assumptions#assumingThat(java.util.function.BooleanSupplier, Executable) * @see org.junit.jupiter.api.DynamicTest#dynamicTest(String, Executable) * @see ThrowingConsumer * @see ThrowingSupplier */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface Executable { void execute() throws Throwable; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingConsumer.java000066400000000000000000000034521455764576500334270ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.function; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code ThrowingConsumer} is a functional interface that can be used to * implement any generic block of code that consumes an argument and * potentially throws a {@link Throwable}. * *

The {@code ThrowingConsumer} interface is similar to * {@link java.util.function.Consumer}, except that a {@code ThrowingConsumer} * can throw any kind of exception, including checked exceptions. * *

Rationale for throwing {@code Throwable} instead of {@code Exception}

* *

Although Java applications typically throw exceptions that are instances * of {@link java.lang.Exception}, {@link java.lang.RuntimeException}, * {@link java.lang.Error}, or {@link java.lang.AssertionError} (in testing * scenarios), there may be use cases where a {@code ThrowingConsumer} needs to * explicitly throw a {@code Throwable}. In order to support such specialized * use cases, {@link #accept} is declared to throw {@code Throwable}. * * @param the type of argument consumed * @since 5.0 * @see java.util.function.Consumer * @see org.junit.jupiter.api.DynamicTest#stream * @see Executable * @see ThrowingSupplier */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface ThrowingConsumer { /** * Consume the supplied argument, potentially throwing an exception. * * @param t the argument to consume */ void accept(T t) throws Throwable; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingSupplier.java000066400000000000000000000035471455764576500334440ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.function; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code ThrowingSupplier} is a functional interface that can be used to * implement any generic block of code that returns an object and * potentially throws a {@link Throwable}. * *

The {@code ThrowingSupplier} interface is similar to * {@link java.util.function.Supplier}, except that a {@code ThrowingSupplier} * can throw any kind of exception, including checked exceptions. * *

Rationale for throwing {@code Throwable} instead of {@code Exception}

* *

Although Java applications typically throw exceptions that are instances * of {@link Exception}, {@link RuntimeException}, * {@link Error}, or {@link AssertionError} (in testing * scenarios), there may be use cases where a {@code ThrowingSupplier} needs to * explicitly throw a {@code Throwable}. In order to support such specialized * use cases, {@link #get} is declared to throw {@code Throwable}. * * @param the type of argument supplied * @since 5.0 * @see java.util.function.Supplier * @see org.junit.jupiter.api.Assertions#assertTimeout(java.time.Duration, ThrowingSupplier) * @see org.junit.jupiter.api.Assertions#assertTimeoutPreemptively(java.time.Duration, ThrowingSupplier) * @see Executable * @see ThrowingConsumer */ @FunctionalInterface @API(status = STABLE, since = "5.0") public interface ThrowingSupplier { /** * Get a result, potentially throwing an exception. * * @return a result */ T get() throws Throwable; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/package-info.java000066400000000000000000000001451455764576500324320ustar00rootroot00000000000000/** * Functional interfaces used within JUnit Jupiter. */ package org.junit.jupiter.api.function; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/000077500000000000000000000000001455764576500260255ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/CleanupMode.java000066400000000000000000000023641455764576500310710ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.io; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; /** * Enumeration of cleanup modes for {@link TempDir @TempDir}. * *

When a test with a temporary directory completes, it might be useful in * some cases to be able to view the contents of the temporary directory used by * the test. {@code CleanupMode} allows you to control how a {@code TempDir} * is cleaned up. * * @since 5.9 * @see TempDir */ @API(status = EXPERIMENTAL, since = "5.9") public enum CleanupMode { /** * Use the default cleanup mode. * * @see TempDir#DEFAULT_CLEANUP_MODE_PROPERTY_NAME */ DEFAULT, /** * Always clean up a temporary directory after the test has completed. */ ALWAYS, /** * Only clean up a temporary directory if the test completed successfully. */ ON_SUCCESS, /** * Never clean up a temporary directory after the test has completed. */ NEVER; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDir.java000066400000000000000000000160501455764576500302360ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.io; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.nio.file.Path; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ParameterResolutionException; /** * {@code @TempDir} can be used to annotate a field in a test class or a * parameter in a lifecycle method or test method of type {@link Path} or * {@link File} that should be resolved into a temporary directory. * *

Please note that {@code @TempDir} is not supported on constructor * parameters. Please use field injection instead by annotating an instance * field with {@code @TempDir}. * *

Creation

* *

The temporary directory is only created if a field in a test class or a * parameter in a lifecycle method or test method is annotated with * {@code @TempDir}. If the field type or parameter type is neither {@link Path} * nor {@link File}, if a field is declared as {@code final}, or if the temporary * directory cannot be created, an {@link ExtensionConfigurationException} or a * {@link ParameterResolutionException} will be thrown as appropriate. In * addition, a {@code ParameterResolutionException} will be thrown for a * constructor parameter annotated with {@code @TempDir}. * *

Scope

* *

By default, a separate temporary directory is created for every * declaration of the {@code @TempDir} annotation. If you want to share a * temporary directory across all tests in a test class, you should declare the * annotation on a {@code static} field or on a parameter of a * {@link org.junit.jupiter.api.BeforeAll @BeforeAll} method. * *

Old behavior

* *

You can revert to the old behavior of using a single temporary directory * by setting the {@value #SCOPE_PROPERTY_NAME} configuration parameter to * {@code per_context}. In that case, the scope of the temporary directory * depends on where the first {@code @TempDir} annotation is encountered when * executing a test class. The temporary directory will be shared by all tests * in a class when the annotation is present on a {@code static} field or on a * parameter of a {@link org.junit.jupiter.api.BeforeAll @BeforeAll} method. * Otherwise — for example, when {@code @TempDir} is only used on instance * fields or on parameters in test, * {@link org.junit.jupiter.api.BeforeEach @BeforeEach}, or * {@link org.junit.jupiter.api.AfterEach @AfterEach} methods — each test * will use its own temporary directory. * *

Clean Up

* *

By default, when the end of the scope of a temporary directory is reached, * — when the test method or class has finished execution — JUnit will * attempt to clean up the temporary directory by recursively deleting all files * and directories in the temporary directory and, finally, the temporary directory * itself. In case deletion of a file or directory fails, an {@link IOException} * will be thrown that will cause the test or test class to fail. * *

The {@link #cleanup} attribute allows you to configure the {@link CleanupMode}. * If the cleanup mode is set to {@link CleanupMode#NEVER NEVER}, the temporary * directory will not be cleaned up after the test completes. If the cleanup mode is * set to {@link CleanupMode#ON_SUCCESS ON_SUCCESS}, the temporary directory will * only be cleaned up if the test completes successfully. By default, the * {@link CleanupMode#ALWAYS ALWAYS} clean up mode will be used, but this can be * configured globally by setting the {@value #DEFAULT_CLEANUP_MODE_PROPERTY_NAME} * configuration parameter. * * @since 5.4 */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.10") public @interface TempDir { /** * Property name used to set the default temporary directory factory class name: * {@value} * *

Supported Values

* *

Supported values include fully qualified class names for types that * implement {@link TempDirFactory}. * *

If not specified, the default is {@link TempDirFactory.Standard}. * * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") String DEFAULT_FACTORY_PROPERTY_NAME = "junit.jupiter.tempdir.factory.default"; /** * Factory for the temporary directory. * *

If the {@value #SCOPE_PROPERTY_NAME} configuration parameter is set to * {@code per_context}, no custom factory is allowed. * *

Defaults to {@link TempDirFactory.Standard}. * *

As an alternative to setting this attribute, a global * {@link TempDirFactory} can be configured for the entire test suite via * the {@value #DEFAULT_FACTORY_PROPERTY_NAME} configuration parameter. * See the User Guide for details. Note, however, that a {@code @TempDir} * declaration with a custom {@code factory} always overrides a global * {@code TempDirFactory}. * * @return the type of {@code TempDirFactory} to use * @since 5.10 * @see TempDirFactory */ @API(status = EXPERIMENTAL, since = "5.10") Class factory() default TempDirFactory.class; /** * Property name used to set the scope of temporary directories created via * the {@link TempDir @TempDir} annotation: {@value} * *

Supported Values

*
    *
  • {@code per_context}: creates a single temporary directory for the * entire test class or method, depending on where it's first declared *
  • {@code per_declaration}: creates separate temporary directories for * each declaration site of the {@code @TempDir} annotation. *
* *

If not specified, the default is {@code per_declaration}. * * @since 5.8 */ @SuppressWarnings("DeprecatedIsStillUsed") @Deprecated @API(status = DEPRECATED, since = "5.9") String SCOPE_PROPERTY_NAME = "junit.jupiter.tempdir.scope"; /** * The name of the configuration parameter that is used to configure the * default {@link CleanupMode}. * *

If this configuration parameter is not set, {@link CleanupMode#ALWAYS} * will be used as the default. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") String DEFAULT_CLEANUP_MODE_PROPERTY_NAME = "junit.jupiter.tempdir.cleanup.mode.default"; /** * How the temporary directory gets cleaned up after the test completes. * * @since 5.9 */ @API(status = EXPERIMENTAL, since = "5.9") CleanupMode cleanup() default CleanupMode.DEFAULT; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDirFactory.java000066400000000000000000000062661455764576500315760ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.io; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ExtensionContext; /** * {@code TempDirFactory} defines the SPI for creating temporary directories * programmatically. * *

A temporary directory factory is typically used to gain control over the * temporary directory creation, like defining the parent directory or the file * system that should be used. * *

Implementations must provide a no-args constructor and should not make any * assumptions regarding when and how many times they are instantiated, but they * can assume that {@link #createTempDirectory(AnnotatedElementContext, ExtensionContext)} * and {@link #close()} will both be called once per instance, in this order, * and from the same thread. * *

A {@link TempDirFactory} can be configured globally for the * entire test suite via the {@value TempDir#DEFAULT_FACTORY_PROPERTY_NAME} * configuration parameter (see the User Guide for details) or locally * for a test class field or method parameter via the {@link TempDir @TempDir} * annotation. * * @since 5.10 * @see TempDir @TempDir */ @FunctionalInterface @API(status = EXPERIMENTAL, since = "5.10") public interface TempDirFactory extends Closeable { /** * Create a new temporary directory. * *

Depending on the implementation, the resulting {@link Path} may or may * not be associated with the {@link java.nio.file.FileSystems#getDefault() * default FileSystem}. * * @param elementContext the context of the field or parameter where * {@code @TempDir} is declared; never {@code null} * @param extensionContext the current extension context; never {@code null} * @return the path to the newly created temporary directory; never {@code null} * @throws Exception in case of failures */ Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception; /** * {@inheritDoc} */ @Override default void close() throws IOException { } /** * Standard {@link TempDirFactory} implementation which delegates to * {@link Files#createTempDirectory} using {@code "junit"} as the prefix. * * @see Files#createTempDirectory(java.lang.String, java.nio.file.attribute.FileAttribute[]) */ class Standard implements TempDirFactory { public static final TempDirFactory INSTANCE = new Standard(); private static final String TEMP_DIR_PREFIX = "junit"; public Standard() { } @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws IOException { return Files.createTempDirectory(TEMP_DIR_PREFIX); } } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/package-info.java000066400000000000000000000001231455764576500312100ustar00rootroot00000000000000/** * IO-related support in JUnit Jupiter. */ package org.junit.jupiter.api.io; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/package-info.java000066400000000000000000000001201455764576500305760ustar00rootroot00000000000000/** * JUnit Jupiter API for writing tests. */ package org.junit.jupiter.api; junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/000077500000000000000000000000001455764576500272125ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Execution.java000066400000000000000000000064411455764576500320250ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Execution} is used to configure the parallel execution * {@linkplain #value mode} of a test class or test method. * *

Since JUnit Jupiter 5.4, this annotation is {@linkplain Inherited inherited} * within class hierarchies. * *

Default Execution Mode

* *

If this annotation is not present, {@link ExecutionMode#SAME_THREAD} is * used unless a default execution mode is defined via one of the following * configuration parameters: * *

*
{@value #DEFAULT_EXECUTION_MODE_PROPERTY_NAME}
*
Default execution mode for all classes and tests
*
{@value #DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME}
*
Default execution mode for top-level classes
*
* *

{@value #DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME} overrides * {@value #DEFAULT_EXECUTION_MODE_PROPERTY_NAME} for top-level classes. * * @see Isolated * @see ResourceLock * @since 5.3 */ @API(status = STABLE, since = "5.10") @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Inherited public @interface Execution { /** * Property name used to set the default test execution mode: {@value} * *

This setting is only effective if parallel execution is enabled. * *

Supported Values

* *

Supported values include names of enum constants defined in * {@link ExecutionMode}, ignoring case. * *

If not specified, the default is "same_thread" which corresponds to * {@code @Execution(ExecutionMode.SAME_THREAD)}. * * @since 5.4 */ @API(status = EXPERIMENTAL, since = "5.9") String DEFAULT_EXECUTION_MODE_PROPERTY_NAME = "junit.jupiter.execution.parallel.mode.default"; /** * Property name used to set the default test execution mode for top-level * classes: {@value} * *

This setting is only effective if parallel execution is enabled. * *

Supported Values

* *

Supported values include names of enum constants defined in * {@link ExecutionMode}, ignoring case. * *

If not specified, it will be resolved into the same value as * {@link #DEFAULT_EXECUTION_MODE_PROPERTY_NAME}. * * @since 5.4 */ @API(status = EXPERIMENTAL, since = "5.9") String DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME = "junit.jupiter.execution.parallel.mode.classes.default"; /** * The required/preferred execution mode. * * @see ExecutionMode */ ExecutionMode value(); /** * The reason for using the selected execution mode. * *

This is for informational purposes only. * * @since 5.10 */ @API(status = STABLE, since = "5.10") String reason() default ""; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ExecutionMode.java000066400000000000000000000015121455764576500326240ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Supported execution modes for parallel test execution. * * @since 5.3 * @see #SAME_THREAD * @see #CONCURRENT */ @API(status = STABLE, since = "5.10") public enum ExecutionMode { /** * Force execution in same thread as the parent node. * * @see #CONCURRENT */ SAME_THREAD, /** * Allow concurrent execution with any other node. * * @see #SAME_THREAD */ CONCURRENT } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Isolated.java000066400000000000000000000027241455764576500316260ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @Isolated} is used to declare that the annotated test class should be * executed in isolation from other test classes. * *

When a test class is run in isolation, no other test class is executed * concurrently. This can be used to enable parallel test execution for the * entire test suite while running some tests in isolation (e.g. if they modify * some global resource). * * @since 5.7 * @see ExecutionMode * @see ResourceLock */ @API(status = STABLE, since = "5.10") @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @ResourceLock(Resources.GLOBAL) public @interface Isolated { /** * The reason this test class needs to run in isolation. * *

The supplied string is currently not reported in any way but can be * used for documentation purposes. */ String value() default ""; } ResourceAccessMode.java000066400000000000000000000014111455764576500335110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * The access mode required by a test class or method for a given resource. * * @since 5.3 * @see ResourceLock */ @API(status = STABLE, since = "5.10") public enum ResourceAccessMode { /** * Require read and write access to the resource. */ READ_WRITE, /** * Require only read access to the resource. */ READ } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLock.java000066400000000000000000000044301455764576500324560ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ResourceLock} is used to declare that the annotated test class or test * method requires access to a shared resource identified by a key. * *

The resource key is specified via {@link #value}. In addition, * {@link #mode} allows you to specify whether the annotated test class or test * method requires {@link ResourceAccessMode#READ_WRITE READ_WRITE} or only * {@link ResourceAccessMode#READ READ} access to the resource. In the former case, * execution of the annotated element will occur while no other test class or * test method that uses the shared resource is being executed. In the latter case, * the annotated element may be executed concurrently with other test classes or * methods that also require {@code READ} access but not at the same time as any * other test that requires {@code READ_WRITE} access. * *

This annotation can be repeated to declare the use of multiple shared resources. * *

Since JUnit Jupiter 5.4, this annotation is {@linkplain Inherited inherited} * within class hierarchies. * * @see Isolated * @see Resources * @see ResourceAccessMode * @see ResourceLocks * @since 5.3 */ @API(status = STABLE, since = "5.10") @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Inherited @Repeatable(ResourceLocks.class) public @interface ResourceLock { /** * The resource key. * * @see Resources */ String value(); /** * The resource access mode. * *

Defaults to {@link ResourceAccessMode#READ_WRITE READ_WRITE}. * * @see ResourceAccessMode */ ResourceAccessMode mode() default ResourceAccessMode.READ_WRITE; } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLocks.java000066400000000000000000000025771455764576500326530ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ResourceLocks} is a container for one or more * {@link ResourceLock @ResourceLock} declarations. * *

Note, however, that use of the {@code @ResourceLocks} container is * completely optional since {@code @ResourceLock} is a * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. * *

Since JUnit Jupiter 5.4, this annotation is {@linkplain Inherited inherited} * within class hierarchies. * * @see ResourceLock * @since 5.3 */ @API(status = STABLE, since = "5.10") @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Inherited public @interface ResourceLocks { /** * An array of one or more {@linkplain ResourceLock @ResourceLock} declarations. */ ResourceLock[] value(); } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Resources.java000066400000000000000000000042351455764576500320330ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.parallel; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Common resource names for synchronizing test execution. * * @since 5.3 * @see ResourceLock */ @API(status = STABLE, since = "5.10") public class Resources { /** * Represents Java's system properties: {@value} * * @see System#getProperties() * @see System#setProperties(java.util.Properties) */ public static final String SYSTEM_PROPERTIES = "java.lang.System.properties"; /** * Represents the standard output stream of the current process: {@value} * * @see System#out * @see System#setOut(java.io.PrintStream) */ public static final String SYSTEM_OUT = "java.lang.System.out"; /** * Represents the standard error stream of the current process: {@value} * * @see System#err * @see System#setErr(java.io.PrintStream) */ public static final String SYSTEM_ERR = "java.lang.System.err"; /** * Represents the default locale for the current instance of the JVM: * {@value} * * @since 5.4 * @see java.util.Locale#setDefault(java.util.Locale) */ @API(status = STABLE, since = "5.10") public static final String LOCALE = "java.util.Locale.default"; /** * Represents the default time zone for the current instance of the JVM: * {@value} * * @since 5.4 * @see java.util.TimeZone#setDefault(java.util.TimeZone) */ @API(status = STABLE, since = "5.10") public static final String TIME_ZONE = "java.util.TimeZone.default"; /** * Represents the global resource lock: {@value} * * @since 5.8 * @see Isolated * @see org.junit.platform.engine.support.hierarchical.ExclusiveResource */ @API(status = STABLE, since = "5.10") public static final String GLOBAL = "org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_KEY"; private Resources() { /* no-op */ } } junit5-r5.10.2/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/package-info.java000066400000000000000000000001571455764576500324040ustar00rootroot00000000000000/** * JUnit Jupiter API for influencing parallel test execution. */ package org.junit.jupiter.api.parallel; junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/000077500000000000000000000000001455764576500216225ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/org/000077500000000000000000000000001455764576500224115ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/org/junit/000077500000000000000000000000001455764576500235425ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/000077500000000000000000000000001455764576500252245ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/000077500000000000000000000000001455764576500257755ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/Assertions.kt000066400000000000000000000202561455764576500304740ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ @file:API(status = STABLE, since = "5.7") package org.junit.jupiter.api import org.apiguardian.api.API import org.apiguardian.api.API.Status.EXPERIMENTAL import org.apiguardian.api.API.Status.STABLE import org.junit.jupiter.api.function.Executable import org.junit.jupiter.api.function.ThrowingSupplier import java.time.Duration import java.util.function.Supplier import java.util.stream.Stream /** * @see Assertions.fail */ fun fail(message: String?, throwable: Throwable? = null): Nothing = Assertions.fail(message, throwable) /** * @see Assertions.fail */ fun fail(message: (() -> String)?): Nothing = Assertions.fail(message) /** * @see Assertions.fail */ fun fail(throwable: Throwable?): Nothing = Assertions.fail(throwable) /** * [Stream] of functions to be executed. */ private typealias ExecutableStream = Stream<() -> Unit> private fun ExecutableStream.convert() = map { Executable(it) } /** * @see Assertions.assertAll */ fun assertAll(executables: ExecutableStream) = Assertions.assertAll(executables.convert()) /** * @see Assertions.assertAll */ fun assertAll(heading: String?, executables: ExecutableStream) = Assertions.assertAll(heading, executables.convert()) /** * [Collection] of functions to be executed. */ private typealias ExecutableCollection = Collection<() -> Unit> private fun ExecutableCollection.convert() = map { Executable(it) } /** * @see Assertions.assertAll */ fun assertAll(executables: ExecutableCollection) = Assertions.assertAll(executables.convert()) /** * @see Assertions.assertAll */ fun assertAll(heading: String?, executables: ExecutableCollection) = Assertions.assertAll(heading, executables.convert()) /** * @see Assertions.assertAll */ fun assertAll(vararg executables: () -> Unit) = assertAll(executables.toList().stream()) /** * @see Assertions.assertAll */ fun assertAll(heading: String?, vararg executables: () -> Unit) = assertAll(heading, executables.toList().stream()) /** * Example usage: * ```kotlin * val exception = assertThrows { * throw IllegalArgumentException("Talk to a duck") * } * assertEquals("Talk to a duck", exception.message) * ``` * @see Assertions.assertThrows */ inline fun assertThrows(executable: () -> Unit): T { val throwable: Throwable? = try { executable() } catch (caught: Throwable) { caught } as? Throwable return Assertions.assertThrows(T::class.java) { if (throwable != null) { throw throwable } } } /** * Example usage: * ```kotlin * val exception = assertThrows("Should throw an Exception") { * throw IllegalArgumentException("Talk to a duck") * } * assertEquals("Talk to a duck", exception.message) * ``` * @see Assertions.assertThrows */ inline fun assertThrows(message: String, executable: () -> Unit): T = assertThrows({ message }, executable) /** * Example usage: * ```kotlin * val exception = assertThrows({ "Should throw an Exception" }) { * throw IllegalArgumentException("Talk to a duck") * } * assertEquals("Talk to a duck", exception.message) * ``` * @see Assertions.assertThrows */ inline fun assertThrows(noinline message: () -> String, executable: () -> Unit): T { val throwable: Throwable? = try { executable() } catch (caught: Throwable) { caught } as? Throwable return Assertions.assertThrows( T::class.java, Executable { if (throwable != null) { throw throwable } }, Supplier(message) ) } /** * Example usage: * ```kotlin * val result = assertDoesNotThrow { * // Code block that is expected to not throw an exception * } * ``` * @see Assertions.assertDoesNotThrow * @param R the result type of the [executable] */ @API(status = EXPERIMENTAL, since = "5.5") inline fun assertDoesNotThrow(executable: () -> R): R = Assertions.assertDoesNotThrow(evaluateAndWrap(executable)) /** * Example usage: * ```kotlin * val result = assertDoesNotThrow("Should not throw an exception") { * // Code block that is expected to not throw an exception * } * ``` * @see Assertions.assertDoesNotThrow * @param R the result type of the [executable] */ @API(status = EXPERIMENTAL, since = "5.5") inline fun assertDoesNotThrow(message: String, executable: () -> R): R = assertDoesNotThrow({ message }, executable) /** * Example usage: * ```kotlin * val result = assertDoesNotThrow({ "Should not throw an exception" }) { * // Code block that is expected to not throw an exception * } * ``` * @see Assertions.assertDoesNotThrow * @param R the result type of the [executable] */ @API(status = EXPERIMENTAL, since = "5.5") inline fun assertDoesNotThrow(noinline message: () -> String, executable: () -> R): R = Assertions.assertDoesNotThrow( evaluateAndWrap(executable), Supplier(message) ) @PublishedApi internal inline fun evaluateAndWrap(executable: () -> R): ThrowingSupplier = try { val result = executable() ThrowingSupplier { result } } catch (throwable: Throwable) { ThrowingSupplier { throw throwable } } /** * Example usage: * ```kotlin * val result = assertTimeout(Duration.seconds(1)) { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeout * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeout(timeout: Duration, executable: () -> R): R = Assertions.assertTimeout(timeout, executable) /** * Example usage: * ```kotlin * val result = assertTimeout(Duration.seconds(1), "Should only take one second") { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeout * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeout(timeout: Duration, message: String, executable: () -> R): R = Assertions.assertTimeout(timeout, executable, message) /** * Example usage: * ```kotlin * val result = assertTimeout(Duration.seconds(1), { "Should only take one second" }) { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeout * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeout(timeout: Duration, message: () -> String, executable: () -> R): R = Assertions.assertTimeout(timeout, executable, message) /** * Example usage: * ```kotlin * val result = assertTimeoutPreemptively(Duration.seconds(1)) { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeoutPreemptively * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeoutPreemptively(timeout: Duration, executable: () -> R): R = Assertions.assertTimeoutPreemptively(timeout, executable) /** * Example usage: * ```kotlin * val result = assertTimeoutPreemptively(Duration.seconds(1), "Should only take one second") { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeoutPreemptively * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeoutPreemptively(timeout: Duration, message: String, executable: () -> R): R = Assertions.assertTimeoutPreemptively(timeout, executable, message) /** * Example usage: * ```kotlin * val result = assertTimeoutPreemptively(Duration.seconds(1), { "Should only take one second" }) { * // Code block that is being timed. * } * ``` * @see Assertions.assertTimeoutPreemptively * @paramR the result of the [executable]. */ @API(status = EXPERIMENTAL, since = "5.5") fun assertTimeoutPreemptively(timeout: Duration, message: () -> String, executable: () -> R): R = Assertions.assertTimeoutPreemptively(timeout, executable, message) junit5-r5.10.2/junit-jupiter-api/src/module/000077500000000000000000000000001455764576500206635ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/module/org.junit.jupiter.api/000077500000000000000000000000001455764576500250335ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/module/org.junit.jupiter.api/module-info.java000066400000000000000000000015141455764576500301150ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Defines JUnit Jupiter API for writing tests. */ module org.junit.jupiter.api { requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; requires transitive org.opentest4j; exports org.junit.jupiter.api; exports org.junit.jupiter.api.condition; exports org.junit.jupiter.api.extension; exports org.junit.jupiter.api.function; exports org.junit.jupiter.api.io; exports org.junit.jupiter.api.parallel; opens org.junit.jupiter.api.condition to org.junit.platform.commons; } junit5-r5.10.2/junit-jupiter-api/src/testFixtures/000077500000000000000000000000001455764576500221075ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/000077500000000000000000000000001455764576500230305ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/000077500000000000000000000000001455764576500236175ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500247505ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/000077500000000000000000000000001455764576500264325ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/000077500000000000000000000000001455764576500272035ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/extension/000077500000000000000000000000001455764576500312175ustar00rootroot00000000000000ExtensionContextParameterResolver.java000066400000000000000000000015411455764576500407100ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; public class ExtensionContextParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return ExtensionContext.class.equals(parameterContext.getParameter().getType()); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext; } } junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/fixtures/000077500000000000000000000000001455764576500310545ustar00rootroot00000000000000TrackLogRecords.java000066400000000000000000000055041455764576500346740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/fixtures/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.fixtures; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.logging.LoggerFactory; /** * {@code @TrackLogRecords} registers an extension that tracks log records * logged via JUnit's logging facade for JUL. * *

Log records are tracked on a per-method basis (e.g., for a single * test method). * *

Test methods can gain access to the {@link LogRecordListener} managed by * the extension by having an instance of {@code LogRecordListener} injected as * a method parameter. * * @since 5.1 * @see LoggerFactory * @see LogRecordListener */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(TrackLogRecords.Extension.class) public @interface TrackLogRecords { class Extension implements BeforeEachCallback, AfterEachCallback, ParameterResolver { @Override public void beforeEach(ExtensionContext context) { LoggerFactory.addListener(getListener(context)); } @Override public void afterEach(ExtensionContext context) { LoggerFactory.removeListener(getListener(context)); } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { boolean isTestMethodLevel = extensionContext.getTestMethod().isPresent(); boolean isListener = parameterContext.getParameter().getType() == LogRecordListener.class; return isTestMethodLevel && isListener; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return getListener(extensionContext); } private LogRecordListener getListener(ExtensionContext context) { return getStore(context).getOrComputeIfAbsent(LogRecordListener.class); } private Store getStore(ExtensionContext context) { return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod())); } } } junit5-r5.10.2/junit-jupiter-engine/000077500000000000000000000000001455764576500173035ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/junit-jupiter-engine.gradle.kts000066400000000000000000000031321455764576500253360ustar00rootroot00000000000000import org.gradle.api.tasks.PathSensitivity.RELATIVE plugins { id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") groovy `java-test-fixtures` } description = "JUnit Jupiter Engine" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformEngine) api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(projects.junitPlatformTestkit) testImplementation(testFixtures(projects.junitPlatformCommons)) testImplementation(kotlin("stdlib")) testImplementation(libs.jimfs) testImplementation(libs.junit4) testImplementation(libs.kotlinx.coroutines) testImplementation(libs.groovy4) testImplementation(libs.memoryfilesystem) testImplementation(testFixtures(projects.junitJupiterApi)) osgiVerification(projects.junitPlatformLauncher) } tasks { test { inputs.dir("src/test/resources").withPathSensitivity(RELATIVE) systemProperty("developmentVersion", version) } jar { bundle { val platformVersion: String by rootProject.extra bnd(""" Provide-Capability:\ org.junit.platform.engine;\ org.junit.platform.engine='junit-jupiter';\ version:Version="${'$'}{version_cleanup;${project.version}}" Require-Capability:\ org.junit.platform.launcher;\ filter:='(&(org.junit.platform.launcher=junit-platform-launcher)(version>=${'$'}{version_cleanup;${platformVersion}})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;${platformVersion}}})))';\ effective:=active """) } } } junit5-r5.10.2/junit-jupiter-engine/src/000077500000000000000000000000001455764576500200725ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/000077500000000000000000000000001455764576500210165ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/000077500000000000000000000000001455764576500217375ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/000077500000000000000000000000001455764576500225265ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/000077500000000000000000000000001455764576500236575ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/000077500000000000000000000000001455764576500253415ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/000077500000000000000000000000001455764576500266065ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java000066400000000000000000000352051455764576500314320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_CUSTOM_CLASS_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_FIXED_PARALLELISM_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_FIXED_SATURATE_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_STRATEGY_PROPERTY_NAME; import org.apiguardian.api.API; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.engine.support.hierarchical.ParallelExecutionConfigurationStrategy; /** * Collection of constants related to the {@link JupiterTestEngine}. * * @since 5.0 * @see org.junit.platform.engine.ConfigurationParameters */ @API(status = STABLE, since = "5.0") public final class Constants { /** * Property name used to provide patterns for deactivating conditions: {@value} * *

Pattern Matching Syntax

* *

If the property value consists solely of an asterisk ({@code *}), all * conditions will be deactivated. Otherwise, the property value will be treated * as a comma-separated list of patterns where each individual pattern will be * matched against the fully qualified class name (FQCN) of each registered * condition. Any dot ({@code .}) in a pattern will match against a dot ({@code .}) * or a dollar sign ({@code $}) in a FQCN. Any asterisk ({@code *}) will match * against one or more characters in a FQCN. All other characters in a pattern * will be matched one-to-one against a FQCN. * *

Examples

* *
    *
  • {@code *}: deactivates all conditions. *
  • {@code org.junit.*}: deactivates every condition under the {@code org.junit} * base package and any of its subpackages. *
  • {@code *.MyCondition}: deactivates every condition whose simple class name is * exactly {@code MyCondition}. *
  • {@code *System*}: deactivates every condition whose FQCN contains * {@code System}. *
  • {@code *System*, *Dev*}: deactivates every condition whose FQCN contains * {@code System} or {@code Dev}. *
  • {@code org.example.MyCondition, org.example.TheirCondition}: deactivates * conditions whose FQCN is exactly {@code org.example.MyCondition} or * {@code org.example.TheirCondition}. *
* * @see #DEACTIVATE_ALL_CONDITIONS_PATTERN * @see org.junit.jupiter.api.extension.ExecutionCondition */ public static final String DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME = JupiterConfiguration.DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME; /** * Wildcard pattern which signals that all conditions should be deactivated: {@value} * * @see #DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME * @see org.junit.jupiter.api.extension.ExecutionCondition */ public static final String DEACTIVATE_ALL_CONDITIONS_PATTERN = ClassNamePatternFilterUtils.DEACTIVATE_ALL_PATTERN; /** * Property name used to set the default display name generator class name: {@value} * * @see DisplayNameGenerator#DEFAULT_GENERATOR_PROPERTY_NAME */ public static final String DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME = DisplayNameGenerator.DEFAULT_GENERATOR_PROPERTY_NAME; /** * Property name used to enable auto-detection and registration of extensions via * Java's {@link java.util.ServiceLoader} mechanism: {@value} * *

The default behavior is not to perform auto-detection. */ public static final String EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME; /** * Property name used to set the default test instance lifecycle mode: {@value} * * @see TestInstance.Lifecycle#DEFAULT_LIFECYCLE_PROPERTY_NAME */ public static final String DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME = TestInstance.Lifecycle.DEFAULT_LIFECYCLE_PROPERTY_NAME; /** * Property name used to enable parallel test execution: {@value} * *

By default, tests are executed sequentially in a single thread. * * @since 5.3 */ @API(status = STABLE, since = "5.10") public static final String PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME = JupiterConfiguration.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; /** * Property name used to set the default test execution mode: {@value} * * @see Execution#DEFAULT_EXECUTION_MODE_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_PARALLEL_EXECUTION_MODE = Execution.DEFAULT_EXECUTION_MODE_PROPERTY_NAME; /** * Property name used to set the default test execution mode for top-level * classes: {@value} * * @see Execution#DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME; static final String PARALLEL_CONFIG_PREFIX = "junit.jupiter.execution.parallel.config."; /** * Property name used to select the * {@link ParallelExecutionConfigurationStrategy}: {@value} * *

Potential values: {@code dynamic} (default), {@code fixed}, or * {@code custom}. * * @since 5.3 */ @API(status = STABLE, since = "5.10") public static final String PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_STRATEGY_PROPERTY_NAME; /** * Property name used to set the desired parallelism for the {@code fixed} * configuration strategy: {@value} * *

No default value; must be a positive integer. * * @since 5.3 */ @API(status = STABLE, since = "5.10") public static final String PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_FIXED_PARALLELISM_PROPERTY_NAME; /** * Property name used to configure the maximum pool size of the underlying * fork-join pool for the {@code fixed} configuration strategy: {@value} * *

Value must be an integer and greater than or equal to * {@value #PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME}; defaults to * {@code 256 + fixed.parallelism}. * *

Note: This property only takes affect on Java 9+. * * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") public static final String PARALLEL_CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME; /** * Property name used to disable saturation of the underlying fork-join pool * for the {@code fixed} configuration strategy: {@value} * *

When set to {@code false} the underlying fork-join pool will reject * additional tasks if all available workers are busy and the maximum * pool-size would be exceeded. *

Value must either {@code true} or {@code false}; defaults to {@code true}. * *

Note: This property only takes affect on Java 9+. * * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") public static final String PARALLEL_CONFIG_FIXED_SATURATE_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_FIXED_SATURATE_PROPERTY_NAME; /** * Property name used to set the factor to be multiplied with the number of * available processors/cores to determine the desired parallelism for the * {@code dynamic} configuration strategy: {@value} * *

Value must be a positive decimal number; defaults to {@code 1}. * * @since 5.3 */ @API(status = STABLE, since = "5.10") public static final String PARALLEL_CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME; /** * Property name used to specify the fully qualified class name of the * {@link ParallelExecutionConfigurationStrategy} to be used for the * {@code custom} configuration strategy: {@value} * * @since 5.3 */ @API(status = STABLE, since = "5.10") public static final String PARALLEL_CONFIG_CUSTOM_CLASS_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_CUSTOM_CLASS_PROPERTY_NAME; /** * Property name used to set the default timeout for all testable and * lifecycle methods: {@value}. * * @see Timeout#DEFAULT_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all testable methods: {@value}. * * @see Timeout#DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link Test @Test} methods: {@value}. * * @see Timeout#DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link TestTemplate @TestTemplate} methods: {@value}. * * @see Timeout#DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link TestFactory @TestFactory} methods: {@value}. * * @see Timeout#DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all lifecycle methods: {@value}. * * @see Timeout#DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link BeforeAll @BeforeAll} methods: {@value}. * * @see Timeout#DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link BeforeEach @BeforeEach} methods: {@value}. * * @see Timeout#DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link AfterEach @AfterEach} methods: {@value}. * * @see Timeout#DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to set the default timeout for all * {@link AfterAll @AfterAll} methods: {@value}. * * @see Timeout#DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME = Timeout.DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME; /** * Property name used to configure whether timeouts are applied to tests: {@value}. * * @see Timeout#TIMEOUT_MODE_PROPERTY_NAME */ @API(status = STABLE, since = "5.10") public static final String TIMEOUT_MODE_PROPERTY_NAME = Timeout.TIMEOUT_MODE_PROPERTY_NAME; /** * Property name used to set the default method orderer class name: {@value} * * @see MethodOrderer#DEFAULT_ORDER_PROPERTY_NAME */ @API(status = STABLE, since = "5.9") public static final String DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME = MethodOrderer.DEFAULT_ORDER_PROPERTY_NAME; /** * Property name used to set the default class orderer class name: {@value} * * @see ClassOrderer#DEFAULT_ORDER_PROPERTY_NAME */ @API(status = STABLE, since = "5.9") public static final String DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME = ClassOrderer.DEFAULT_ORDER_PROPERTY_NAME; /** * Property name used to set the scope of temporary directories created via * the {@link TempDir @TempDir} annotation: {@value} * * @see TempDir#SCOPE_PROPERTY_NAME */ @Deprecated @API(status = DEPRECATED, since = "5.8") @SuppressWarnings("deprecation") public static final String TEMP_DIR_SCOPE_PROPERTY_NAME = TempDir.SCOPE_PROPERTY_NAME; /** * Property name used to set the default timeout thread mode. * * @since 5.9 * @see Timeout * @see Timeout.ThreadMode */ @API(status = EXPERIMENTAL, since = "5.9") public static final String DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME = Timeout.DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME; /** * Property name used to set the default factory for temporary directories created via * the {@link TempDir @TempDir} annotation: {@value} * * @since 5.10 * @see TempDir#DEFAULT_FACTORY_PROPERTY_NAME */ @API(status = EXPERIMENTAL, since = "5.10") public static final String DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME = TempDir.DEFAULT_FACTORY_PROPERTY_NAME; private Constants() { /* no-op */ } } junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/JupiterTestEngine.java000066400000000000000000000074001455764576500330620ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.engine.config.CachingJupiterConfiguration; import org.junit.jupiter.engine.config.DefaultJupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.discovery.DiscoverySelectorResolver; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.config.PrefixedConfigurationParameters; import org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService; import org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine; import org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * The JUnit Jupiter {@link org.junit.platform.engine.TestEngine TestEngine}. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public final class JupiterTestEngine extends HierarchicalTestEngine { @Override public String getId() { return JupiterEngineDescriptor.ENGINE_ID; } /** * Returns {@code org.junit.jupiter} as the group ID. */ @Override public Optional getGroupId() { return Optional.of("org.junit.jupiter"); } /** * Returns {@code junit-jupiter-engine} as the artifact ID. */ @Override public Optional getArtifactId() { return Optional.of("junit-jupiter-engine"); } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { JupiterConfiguration configuration = new CachingJupiterConfiguration( new DefaultJupiterConfiguration(discoveryRequest.getConfigurationParameters())); JupiterEngineDescriptor engineDescriptor = new JupiterEngineDescriptor(uniqueId, configuration); new DiscoverySelectorResolver().resolveSelectors(discoveryRequest, engineDescriptor); return engineDescriptor; } @Override protected HierarchicalTestExecutorService createExecutorService(ExecutionRequest request) { JupiterConfiguration configuration = getJupiterConfiguration(request); if (configuration.isParallelExecutionEnabled()) { return new ForkJoinPoolHierarchicalTestExecutorService(new PrefixedConfigurationParameters( request.getConfigurationParameters(), Constants.PARALLEL_CONFIG_PREFIX)); } return super.createExecutorService(request); } @Override protected JupiterEngineExecutionContext createExecutionContext(ExecutionRequest request) { return new JupiterEngineExecutionContext(request.getEngineExecutionListener(), getJupiterConfiguration(request)); } /** * @since 5.4 */ @Override protected ThrowableCollector.Factory createThrowableCollectorFactory(ExecutionRequest request) { return JupiterThrowableCollectorFactory::createThrowableCollector; } private JupiterConfiguration getJupiterConfiguration(ExecutionRequest request) { JupiterEngineDescriptor engineDescriptor = (JupiterEngineDescriptor) request.getRootTestDescriptor(); return engineDescriptor.getConfiguration(); } } junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/000077500000000000000000000000001455764576500300535ustar00rootroot00000000000000CachingJupiterConfiguration.java000066400000000000000000000106041455764576500362670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.api.io.TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.io.TempDir.DEFAULT_FACTORY_PROPERTY_NAME; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.ExecutionMode; /** * Caching implementation of the {@link JupiterConfiguration} API. * * @since 5.4 */ @API(status = INTERNAL, since = "5.4") public class CachingJupiterConfiguration implements JupiterConfiguration { private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); private final JupiterConfiguration delegate; public CachingJupiterConfiguration(JupiterConfiguration delegate) { this.delegate = delegate; } @Override public Optional getRawConfigurationParameter(String key) { return delegate.getRawConfigurationParameter(key); } @Override public Optional getRawConfigurationParameter(String key, Function transformer) { return delegate.getRawConfigurationParameter(key, transformer); } @Override public boolean isParallelExecutionEnabled() { return (boolean) cache.computeIfAbsent(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, key -> delegate.isParallelExecutionEnabled()); } @Override public boolean isExtensionAutoDetectionEnabled() { return (boolean) cache.computeIfAbsent(EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME, key -> delegate.isExtensionAutoDetectionEnabled()); } @Override public ExecutionMode getDefaultExecutionMode() { return (ExecutionMode) cache.computeIfAbsent(DEFAULT_EXECUTION_MODE_PROPERTY_NAME, key -> delegate.getDefaultExecutionMode()); } @Override public ExecutionMode getDefaultClassesExecutionMode() { return (ExecutionMode) cache.computeIfAbsent(DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME, key -> delegate.getDefaultClassesExecutionMode()); } @Override public TestInstance.Lifecycle getDefaultTestInstanceLifecycle() { return (TestInstance.Lifecycle) cache.computeIfAbsent(DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME, key -> delegate.getDefaultTestInstanceLifecycle()); } @SuppressWarnings("unchecked") @Override public Predicate getExecutionConditionFilter() { return (Predicate) cache.computeIfAbsent(DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME, key -> delegate.getExecutionConditionFilter()); } @Override public DisplayNameGenerator getDefaultDisplayNameGenerator() { return (DisplayNameGenerator) cache.computeIfAbsent(DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME, key -> delegate.getDefaultDisplayNameGenerator()); } @SuppressWarnings("unchecked") @Override public Optional getDefaultTestMethodOrderer() { return (Optional) cache.computeIfAbsent(DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME, key -> delegate.getDefaultTestMethodOrderer()); } @SuppressWarnings("unchecked") @Override public Optional getDefaultTestClassOrderer() { return (Optional) cache.computeIfAbsent(DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME, key -> delegate.getDefaultTestClassOrderer()); } @Override public CleanupMode getDefaultTempDirCleanupMode() { return (CleanupMode) cache.computeIfAbsent(DEFAULT_CLEANUP_MODE_PROPERTY_NAME, key -> delegate.getDefaultTempDirCleanupMode()); } @SuppressWarnings("unchecked") @Override public Supplier getDefaultTempDirFactorySupplier() { return (Supplier) cache.computeIfAbsent(DEFAULT_FACTORY_PROPERTY_NAME, key -> delegate.getDefaultTempDirFactorySupplier()); } } DefaultJupiterConfiguration.java000066400000000000000000000133731455764576500363250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.api.io.TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.io.TempDir.DEFAULT_FACTORY_PROPERTY_NAME; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; /** * Default implementation of the {@link JupiterConfiguration} API. * * @since 5.4 */ @API(status = INTERNAL, since = "5.4") public class DefaultJupiterConfiguration implements JupiterConfiguration { private static final EnumConfigurationParameterConverter executionModeConverter = // new EnumConfigurationParameterConverter<>(ExecutionMode.class, "parallel execution mode"); private static final EnumConfigurationParameterConverter lifecycleConverter = // new EnumConfigurationParameterConverter<>(Lifecycle.class, "test instance lifecycle mode"); private static final InstantiatingConfigurationParameterConverter displayNameGeneratorConverter = // new InstantiatingConfigurationParameterConverter<>(DisplayNameGenerator.class, "display name generator"); private static final InstantiatingConfigurationParameterConverter methodOrdererConverter = // new InstantiatingConfigurationParameterConverter<>(MethodOrderer.class, "method orderer"); private static final InstantiatingConfigurationParameterConverter classOrdererConverter = // new InstantiatingConfigurationParameterConverter<>(ClassOrderer.class, "class orderer"); private static final EnumConfigurationParameterConverter cleanupModeConverter = // new EnumConfigurationParameterConverter<>(CleanupMode.class, "cleanup mode"); private static final InstantiatingConfigurationParameterConverter tempDirFactoryConverter = // new InstantiatingConfigurationParameterConverter<>(TempDirFactory.class, "temp dir factory"); private final ConfigurationParameters configurationParameters; public DefaultJupiterConfiguration(ConfigurationParameters configurationParameters) { this.configurationParameters = Preconditions.notNull(configurationParameters, "ConfigurationParameters must not be null"); } @Override public Optional getRawConfigurationParameter(String key) { return configurationParameters.get(key); } @Override public Optional getRawConfigurationParameter(String key, Function transformer) { return configurationParameters.get(key, transformer); } @Override public boolean isParallelExecutionEnabled() { return configurationParameters.getBoolean(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME).orElse(false); } @Override public boolean isExtensionAutoDetectionEnabled() { return configurationParameters.getBoolean(EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME).orElse(false); } @Override public ExecutionMode getDefaultExecutionMode() { return executionModeConverter.get(configurationParameters, DEFAULT_EXECUTION_MODE_PROPERTY_NAME, ExecutionMode.SAME_THREAD); } @Override public ExecutionMode getDefaultClassesExecutionMode() { return executionModeConverter.get(configurationParameters, DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME, getDefaultExecutionMode()); } @Override public Lifecycle getDefaultTestInstanceLifecycle() { return lifecycleConverter.get(configurationParameters, DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME, Lifecycle.PER_METHOD); } @Override public Predicate getExecutionConditionFilter() { return ClassNamePatternFilterUtils.excludeMatchingClasses( configurationParameters.get(DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME).orElse(null)); } @Override public DisplayNameGenerator getDefaultDisplayNameGenerator() { return displayNameGeneratorConverter.get(configurationParameters, DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME) // .orElseGet(() -> DisplayNameGenerator.getDisplayNameGenerator(DisplayNameGenerator.Standard.class)); } @Override public Optional getDefaultTestMethodOrderer() { return methodOrdererConverter.get(configurationParameters, DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME); } @Override public Optional getDefaultTestClassOrderer() { return classOrdererConverter.get(configurationParameters, DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME); } @Override public CleanupMode getDefaultTempDirCleanupMode() { return cleanupModeConverter.get(configurationParameters, DEFAULT_CLEANUP_MODE_PROPERTY_NAME, ALWAYS); } @Override public Supplier getDefaultTempDirFactorySupplier() { Supplier> supplier = tempDirFactoryConverter.supply(configurationParameters, DEFAULT_FACTORY_PROPERTY_NAME); return () -> supplier.get().orElse(TempDirFactory.Standard.INSTANCE); } } EnumConfigurationParameterConverter.java000066400000000000000000000043651455764576500400340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Locale; import java.util.Optional; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; /** * @since 5.4 */ @API(status = INTERNAL, since = "5.8") public class EnumConfigurationParameterConverter> { private static final Logger logger = LoggerFactory.getLogger(EnumConfigurationParameterConverter.class); private final Class enumType; private final String enumDisplayName; public EnumConfigurationParameterConverter(Class enumType, String enumDisplayName) { this.enumType = enumType; this.enumDisplayName = enumDisplayName; } E get(ConfigurationParameters configParams, String key, E defaultValue) { Preconditions.notNull(configParams, "ConfigurationParameters must not be null"); return get(key, configParams::get, defaultValue); } public E get(String key, Function> lookup, E defaultValue) { Optional value = lookup.apply(key); if (value.isPresent()) { String constantName = null; try { constantName = value.get().trim().toUpperCase(Locale.ROOT); E result = Enum.valueOf(enumType, constantName); logger.config(() -> String.format("Using %s '%s' set via the '%s' configuration parameter.", enumDisplayName, result, key)); return result; } catch (Exception ex) { // local copy necessary for use in lambda expression String constant = constantName; logger.warn(() -> String.format( "Invalid %s '%s' set via the '%s' configuration parameter. " + "Falling back to the %s default value.", enumDisplayName, constant, key, defaultValue.name())); } } return defaultValue; } } InstantiatingConfigurationParameterConverter.java000066400000000000000000000046601455764576500417420ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import java.util.Optional; import java.util.function.Supplier; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.ConfigurationParameters; /** * @since 5.5 */ class InstantiatingConfigurationParameterConverter { private static final Logger logger = LoggerFactory.getLogger(InstantiatingConfigurationParameterConverter.class); private final Class clazz; private final String name; public InstantiatingConfigurationParameterConverter(Class clazz, String name) { this.clazz = clazz; this.name = name; } Optional get(ConfigurationParameters configurationParameters, String key) { return supply(configurationParameters, key).get(); } Supplier> supply(ConfigurationParameters configurationParameters, String key) { // @formatter:off return configurationParameters.get(key) .map(String::trim) .filter(className -> !className.isEmpty()) .map(className -> newInstanceSupplier(className, key)) .orElse(Optional::empty); // @formatter:on } private Supplier> newInstanceSupplier(String className, String key) { Try> clazz = ReflectionUtils.tryToLoadClass(className); // @formatter:off return () -> clazz.andThenTry(ReflectionUtils::newInstance) .andThenTry(this.clazz::cast) .ifSuccess(generator -> logSuccessMessage(className, key)) .ifFailure(cause -> logFailureMessage(className, key, cause)) .toOptional(); // @formatter:on } private void logFailureMessage(String className, String key, Exception cause) { logger.warn(cause, () -> String.format("Failed to load default %s class '%s' set via the '%s' configuration parameter." + " Falling back to default behavior.", this.name, className, key)); } private void logSuccessMessage(String className, String key) { logger.config(() -> String.format("Using default %s '%s' set via the '%s' configuration parameter.", this.name, className, key)); } } JupiterConfiguration.java000066400000000000000000000053121455764576500350120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; /** * @since 5.4 */ @API(status = INTERNAL, since = "5.4") public interface JupiterConfiguration { String DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME = "junit.jupiter.conditions.deactivate"; String PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME = "junit.jupiter.execution.parallel.enabled"; String DEFAULT_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_EXECUTION_MODE_PROPERTY_NAME; String DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME; String EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME = "junit.jupiter.extensions.autodetection.enabled"; String DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME = TestInstance.Lifecycle.DEFAULT_LIFECYCLE_PROPERTY_NAME; String DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME = DisplayNameGenerator.DEFAULT_GENERATOR_PROPERTY_NAME; String DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME = MethodOrderer.DEFAULT_ORDER_PROPERTY_NAME; String DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME = ClassOrderer.DEFAULT_ORDER_PROPERTY_NAME; Optional getRawConfigurationParameter(String key); Optional getRawConfigurationParameter(String key, Function transformer); boolean isParallelExecutionEnabled(); boolean isExtensionAutoDetectionEnabled(); ExecutionMode getDefaultExecutionMode(); ExecutionMode getDefaultClassesExecutionMode(); TestInstance.Lifecycle getDefaultTestInstanceLifecycle(); Predicate getExecutionConditionFilter(); DisplayNameGenerator getDefaultDisplayNameGenerator(); Optional getDefaultTestMethodOrderer(); Optional getDefaultTestClassOrderer(); CleanupMode getDefaultTempDirCleanupMode(); Supplier getDefaultTempDirFactorySupplier(); } junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/package-info.java000066400000000000000000000001561455764576500332440ustar00rootroot00000000000000/** * Configuration specific to the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.config; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/000077500000000000000000000000001455764576500307645ustar00rootroot00000000000000AbstractExtensionContext.java000066400000000000000000000121671455764576500365640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.NamespaceAwareStore; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.hierarchical.Node; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; /** * @since 5.0 */ abstract class AbstractExtensionContext implements ExtensionContext, AutoCloseable { private static final NamespacedHierarchicalStore.CloseAction CLOSE_RESOURCES = (__, ___, value) -> { if (value instanceof CloseableResource) { ((CloseableResource) value).close(); } }; private final ExtensionContext parent; private final EngineExecutionListener engineExecutionListener; private final T testDescriptor; private final Set tags; private final JupiterConfiguration configuration; private final NamespacedHierarchicalStore valuesStore; private final ExecutableInvoker executableInvoker; AbstractExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, T testDescriptor, JupiterConfiguration configuration, ExecutableInvoker executableInvoker) { this.executableInvoker = executableInvoker; Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); Preconditions.notNull(configuration, "JupiterConfiguration must not be null"); this.parent = parent; this.engineExecutionListener = engineExecutionListener; this.testDescriptor = testDescriptor; this.configuration = configuration; this.valuesStore = createStore(parent); // @formatter:off this.tags = testDescriptor.getTags().stream() .map(TestTag::getName) .collect(collectingAndThen(toCollection(LinkedHashSet::new), Collections::unmodifiableSet)); // @formatter:on } private NamespacedHierarchicalStore createStore(ExtensionContext parent) { NamespacedHierarchicalStore parentStore = null; if (parent != null) { parentStore = ((AbstractExtensionContext) parent).valuesStore; } return new NamespacedHierarchicalStore<>(parentStore, CLOSE_RESOURCES); } @Override public void close() { this.valuesStore.close(); } @Override public String getUniqueId() { return getTestDescriptor().getUniqueId().toString(); } @Override public String getDisplayName() { return getTestDescriptor().getDisplayName(); } @Override public void publishReportEntry(Map values) { this.engineExecutionListener.reportingEntryPublished(this.testDescriptor, ReportEntry.from(values)); } @Override public Optional getParent() { return Optional.ofNullable(this.parent); } @Override public ExtensionContext getRoot() { if (this.parent != null) { return this.parent.getRoot(); } return this; } protected T getTestDescriptor() { return this.testDescriptor; } @Override public Store getStore(Namespace namespace) { Preconditions.notNull(namespace, "Namespace must not be null"); return new NamespaceAwareStore(this.valuesStore, namespace); } @Override public Set getTags() { // return modifiable copy return new LinkedHashSet<>(this.tags); } @Override public Optional getConfigurationParameter(String key) { return this.configuration.getRawConfigurationParameter(key); } @Override public Optional getConfigurationParameter(String key, Function transformer) { return this.configuration.getRawConfigurationParameter(key, transformer); } @Override public ExecutionMode getExecutionMode() { return toJupiterExecutionMode(getPlatformExecutionMode()); } @Override public ExecutableInvoker getExecutableInvoker() { return executableInvoker; } protected abstract Node.ExecutionMode getPlatformExecutionMode(); private ExecutionMode toJupiterExecutionMode(Node.ExecutionMode mode) { switch (mode) { case CONCURRENT: return ExecutionMode.CONCURRENT; case SAME_THREAD: return ExecutionMode.SAME_THREAD; } throw new JUnitException("Unknown ExecutionMode: " + mode); } } ClassBasedTestDescriptor.java000066400000000000000000000553401455764576500364620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromConstructorParameters; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromExecutableParameters; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromFields; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findAfterAllMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findAfterEachMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findBeforeAllMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findBeforeEachMethods; import static org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils.getTestInstanceLifecycle; import static org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory.createThrowableCollector; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.LifecycleMethodExecutionExceptionHandler; import org.junit.jupiter.api.extension.TestInstanceFactory; import org.junit.jupiter.api.extension.TestInstanceFactoryContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.api.extension.TestInstancePreConstructCallback; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestInstantiationException; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.AfterEachMethodAdapter; import org.junit.jupiter.engine.execution.BeforeEachMethodAdapter; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.execution.DefaultTestInstances; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.TestInstancesProvider; import org.junit.jupiter.engine.extension.ExtensionRegistrar; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * {@link TestDescriptor} for tests based on Java classes. * * @since 5.5 */ @API(status = INTERNAL, since = "5.5") public abstract class ClassBasedTestDescriptor extends JupiterTestDescriptor { private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); private final Class testClass; protected final Set tags; protected final Lifecycle lifecycle; private ExecutionMode defaultChildExecutionMode; private TestInstanceFactory testInstanceFactory; private List beforeAllMethods; private List afterAllMethods; ClassBasedTestDescriptor(UniqueId uniqueId, Class testClass, Supplier displayNameSupplier, JupiterConfiguration configuration) { super(uniqueId, testClass, displayNameSupplier, ClassSource.from(testClass), configuration); this.testClass = testClass; this.tags = getTags(testClass); this.lifecycle = getTestInstanceLifecycle(testClass, configuration); this.defaultChildExecutionMode = (this.lifecycle == Lifecycle.PER_CLASS ? ExecutionMode.SAME_THREAD : null); } // --- TestDescriptor ------------------------------------------------------ public final Class getTestClass() { return this.testClass; } public abstract List> getEnclosingTestClasses(); @Override public Type getType() { return Type.CONTAINER; } @Override public String getLegacyReportingName() { return this.testClass.getName(); } // --- Node ---------------------------------------------------------------- @Override protected Optional getExplicitExecutionMode() { return getExecutionModeFromAnnotation(getTestClass()); } @Override protected Optional getDefaultChildExecutionMode() { return Optional.ofNullable(this.defaultChildExecutionMode); } public void setDefaultChildExecutionMode(ExecutionMode defaultChildExecutionMode) { this.defaultChildExecutionMode = defaultChildExecutionMode; } @Override public Set getExclusiveResources() { return getExclusiveResourcesFromAnnotation(getTestClass()); } @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation( context.getExtensionRegistry(), this.testClass); // Register extensions from static fields here, at the class level but // after extensions registered via @ExtendWith. registerExtensionsFromFields(registry, this.testClass, null); // Resolve the TestInstanceFactory at the class level in order to fail // the entire class in case of configuration errors (e.g., more than // one factory registered per class). this.testInstanceFactory = resolveTestInstanceFactory(registry); if (this.testInstanceFactory == null) { registerExtensionsFromConstructorParameters(registry, this.testClass); } this.beforeAllMethods = findBeforeAllMethods(this.testClass, this.lifecycle == Lifecycle.PER_METHOD); this.afterAllMethods = findAfterAllMethods(this.testClass, this.lifecycle == Lifecycle.PER_METHOD); this.beforeAllMethods.forEach(method -> registerExtensionsFromExecutableParameters(registry, method)); // Since registerBeforeEachMethodAdapters() and registerAfterEachMethodAdapters() also // invoke registerExtensionsFromExecutableParameters(), we invoke those methods before // invoking registerExtensionsFromExecutableParameters() for @AfterAll methods, // thereby ensuring proper registration order for extensions registered via @ExtendWith // on parameters in lifecycle methods. registerBeforeEachMethodAdapters(registry); registerAfterEachMethodAdapters(registry); this.afterAllMethods.forEach(method -> registerExtensionsFromExecutableParameters(registry, method)); ThrowableCollector throwableCollector = createThrowableCollector(); ExecutableInvoker executableInvoker = new DefaultExecutableInvoker(context); ClassExtensionContext extensionContext = new ClassExtensionContext(context.getExtensionContext(), context.getExecutionListener(), this, this.lifecycle, context.getConfiguration(), throwableCollector, executableInvoker); // @formatter:off return context.extend() .withTestInstancesProvider(testInstancesProvider(context, extensionContext)) .withExtensionRegistry(registry) .withExtensionContext(extensionContext) .withThrowableCollector(throwableCollector) .build(); // @formatter:on } @Override public JupiterEngineExecutionContext before(JupiterEngineExecutionContext context) { ThrowableCollector throwableCollector = context.getThrowableCollector(); if (isPerClassLifecycle(context)) { // Eagerly load test instance for BeforeAllCallbacks, if necessary, // and store the instance in the ExtensionContext. ClassExtensionContext extensionContext = (ClassExtensionContext) context.getExtensionContext(); throwableCollector.execute(() -> { TestInstances testInstances = context.getTestInstancesProvider().getTestInstances( context.getExtensionRegistry(), throwableCollector); extensionContext.setTestInstances(testInstances); }); } if (throwableCollector.isEmpty()) { context.beforeAllCallbacksExecuted(true); invokeBeforeAllCallbacks(context); if (throwableCollector.isEmpty()) { context.beforeAllMethodsExecuted(true); invokeBeforeAllMethods(context); } } throwableCollector.assertEmpty(); return context; } @Override public void after(JupiterEngineExecutionContext context) { ThrowableCollector throwableCollector = context.getThrowableCollector(); Throwable previousThrowable = throwableCollector.getThrowable(); if (context.beforeAllMethodsExecuted()) { invokeAfterAllMethods(context); } if (context.beforeAllCallbacksExecuted()) { invokeAfterAllCallbacks(context); } if (isPerClassLifecycle(context) && context.getExtensionContext().getTestInstance().isPresent()) { invokeTestInstancePreDestroyCallbacks(context); } // If the previous Throwable was not null when this method was called, // that means an exception was already thrown either before or during // the execution of this Node. If an exception was already thrown, any // later exceptions were added as suppressed exceptions to that original // exception unless a more severe exception occurred in the meantime. if (previousThrowable != throwableCollector.getThrowable()) { throwableCollector.assertEmpty(); } } private TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) { List factories = registry.getExtensions(TestInstanceFactory.class); if (factories.size() == 1) { return factories.get(0); } if (factories.size() > 1) { String factoryNames = factories.stream()// .map(factory -> factory.getClass().getName())// .collect(joining(", ")); String errorMessage = String.format( "The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s", testClass.getName(), factoryNames); throw new ExtensionConfigurationException(errorMessage); } return null; } private TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext, ClassExtensionContext extensionContext) { return (registry, registrar, throwableCollector) -> extensionContext.getTestInstances().orElseGet( () -> instantiateAndPostProcessTestInstance(parentExecutionContext, extensionContext, registry, registrar, throwableCollector)); } private TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext, ExtensionContext extensionContext, ExtensionRegistry registry, ExtensionRegistrar registrar, ThrowableCollector throwableCollector) { TestInstances instances = instantiateTestClass(parentExecutionContext, registry, registrar, extensionContext, throwableCollector); throwableCollector.execute(() -> { invokeTestInstancePostProcessors(instances.getInnermostInstance(), registry, extensionContext); // In addition, we register extensions from instance fields here since the // best time to do that is immediately following test class instantiation // and post processing. registerExtensionsFromFields(registrar, this.testClass, instances.getInnermostInstance()); }); return instances; } protected abstract TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext, ThrowableCollector throwableCollector); protected TestInstances instantiateTestClass(Optional outerInstances, ExtensionRegistry registry, ExtensionContext extensionContext) { Optional outerInstance = outerInstances.map(TestInstances::getInnermostInstance); invokeTestInstancePreConstructCallbacks(new DefaultTestInstanceFactoryContext(this.testClass, outerInstance), registry, extensionContext); Object instance = this.testInstanceFactory != null // ? invokeTestInstanceFactory(outerInstance, extensionContext) // : invokeTestClassConstructor(outerInstance, registry, extensionContext); return outerInstances.map(instances -> DefaultTestInstances.of(instances, instance)).orElse( DefaultTestInstances.of(instance)); } private Object invokeTestInstanceFactory(Optional outerInstance, ExtensionContext extensionContext) { Object instance; try { instance = this.testInstanceFactory.createTestInstance( new DefaultTestInstanceFactoryContext(this.testClass, outerInstance), extensionContext); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); if (throwable instanceof TestInstantiationException) { throw (TestInstantiationException) throwable; } String message = String.format("TestInstanceFactory [%s] failed to instantiate test class [%s]", this.testInstanceFactory.getClass().getName(), this.testClass.getName()); if (StringUtils.isNotBlank(throwable.getMessage())) { message += ": " + throwable.getMessage(); } throw new TestInstantiationException(message, throwable); } if (!this.testClass.isInstance(instance)) { String testClassName = this.testClass.getName(); Class instanceClass = (instance == null ? null : instance.getClass()); String instanceClassName = (instanceClass == null ? "null" : instanceClass.getName()); // If the test instance was loaded via a different ClassLoader, append // the identity hash codes to the type names to help users disambiguate // between otherwise identical "fully qualified class names". if (testClassName.equals(instanceClassName)) { testClassName += "@" + Integer.toHexString(System.identityHashCode(this.testClass)); instanceClassName += "@" + Integer.toHexString(System.identityHashCode(instanceClass)); } String message = String.format( "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].", this.testInstanceFactory.getClass().getName(), testClassName, instanceClassName); throw new TestInstantiationException(message); } return instance; } private Object invokeTestClassConstructor(Optional outerInstance, ExtensionRegistry registry, ExtensionContext extensionContext) { Constructor constructor = ReflectionUtils.getDeclaredConstructor(this.testClass); return executableInvoker.invoke(constructor, outerInstance, extensionContext, registry, InvocationInterceptor::interceptTestClassConstructor); } private void invokeTestInstancePreConstructCallbacks(TestInstanceFactoryContext factoryContext, ExtensionRegistry registry, ExtensionContext context) { registry.stream(TestInstancePreConstructCallback.class).forEach( extension -> executeAndMaskThrowable(() -> extension.preConstructTestInstance(factoryContext, context))); } private void invokeTestInstancePostProcessors(Object instance, ExtensionRegistry registry, ExtensionContext context) { registry.stream(TestInstancePostProcessor.class).forEach( extension -> executeAndMaskThrowable(() -> extension.postProcessTestInstance(instance, context))); } private void executeAndMaskThrowable(Executable executable) { try { executable.execute(); } catch (Throwable throwable) { ExceptionUtils.throwAsUncheckedException(throwable); } } private void invokeBeforeAllCallbacks(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); for (BeforeAllCallback callback : registry.getExtensions(BeforeAllCallback.class)) { throwableCollector.execute(() -> callback.beforeAll(extensionContext)); if (throwableCollector.isNotEmpty()) { break; } } } private void invokeBeforeAllMethods(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); Object testInstance = extensionContext.getTestInstance().orElse(null); for (Method method : this.beforeAllMethods) { throwableCollector.execute(() -> { try { executableInvoker.invoke(method, testInstance, extensionContext, registry, ReflectiveInterceptorCall.ofVoidMethod(InvocationInterceptor::interceptBeforeAllMethod)); } catch (Throwable throwable) { invokeBeforeAllMethodExecutionExceptionHandlers(registry, extensionContext, throwable); } }); if (throwableCollector.isNotEmpty()) { break; } } } private void invokeBeforeAllMethodExecutionExceptionHandlers(ExtensionRegistry registry, ExtensionContext context, Throwable throwable) { invokeExecutionExceptionHandlers(LifecycleMethodExecutionExceptionHandler.class, registry, throwable, (handler, handledThrowable) -> handler.handleBeforeAllMethodExecutionException(context, handledThrowable)); } private void invokeAfterAllMethods(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); Object testInstance = extensionContext.getTestInstance().orElse(null); this.afterAllMethods.forEach(method -> throwableCollector.execute(() -> { try { executableInvoker.invoke(method, testInstance, extensionContext, registry, ReflectiveInterceptorCall.ofVoidMethod(InvocationInterceptor::interceptAfterAllMethod)); } catch (Throwable throwable) { invokeAfterAllMethodExecutionExceptionHandlers(registry, extensionContext, throwable); } })); } private void invokeAfterAllMethodExecutionExceptionHandlers(ExtensionRegistry registry, ExtensionContext context, Throwable throwable) { invokeExecutionExceptionHandlers(LifecycleMethodExecutionExceptionHandler.class, registry, throwable, (handler, handledThrowable) -> handler.handleAfterAllMethodExecutionException(context, handledThrowable)); } private void invokeAfterAllCallbacks(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); forEachInReverseOrder(registry.getExtensions(AfterAllCallback.class), // extension -> throwableCollector.execute(() -> extension.afterAll(extensionContext))); } private void invokeTestInstancePreDestroyCallbacks(JupiterEngineExecutionContext context) { ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); forEachInReverseOrder(context.getExtensionRegistry().getExtensions(TestInstancePreDestroyCallback.class), // extension -> throwableCollector.execute(() -> extension.preDestroyTestInstance(extensionContext))); } private boolean isPerClassLifecycle(JupiterEngineExecutionContext context) { return context.getExtensionContext().getTestInstanceLifecycle().orElse( Lifecycle.PER_METHOD) == Lifecycle.PER_CLASS; } private void registerBeforeEachMethodAdapters(ExtensionRegistrar registrar) { List beforeEachMethods = findBeforeEachMethods(this.testClass); registerMethodsAsExtensions(beforeEachMethods, registrar, this::synthesizeBeforeEachMethodAdapter); } private void registerAfterEachMethodAdapters(ExtensionRegistrar registrar) { // Make a local copy since findAfterEachMethods() returns an immutable list. List afterEachMethods = new ArrayList<>(findAfterEachMethods(this.testClass)); // Since the bottom-up ordering of afterEachMethods will later be reversed when the // synthesized AfterEachMethodAdapters are executed within TestMethodTestDescriptor, // we have to reverse the afterEachMethods list to put them in top-down order before // we register them as synthesized extensions. Collections.reverse(afterEachMethods); registerMethodsAsExtensions(afterEachMethods, registrar, this::synthesizeAfterEachMethodAdapter); } private void registerMethodsAsExtensions(List methods, ExtensionRegistrar registrar, Function extensionSynthesizer) { methods.forEach(method -> { registerExtensionsFromExecutableParameters(registrar, method); registrar.registerSyntheticExtension(extensionSynthesizer.apply(method), method); }); } private BeforeEachMethodAdapter synthesizeBeforeEachMethodAdapter(Method method) { return (extensionContext, registry) -> invokeMethodInExtensionContext(method, extensionContext, registry, InvocationInterceptor::interceptBeforeEachMethod); } private AfterEachMethodAdapter synthesizeAfterEachMethodAdapter(Method method) { return (extensionContext, registry) -> invokeMethodInExtensionContext(method, extensionContext, registry, InvocationInterceptor::interceptAfterEachMethod); } private void invokeMethodInExtensionContext(Method method, ExtensionContext context, ExtensionRegistry registry, VoidMethodInterceptorCall interceptorCall) { TestInstances testInstances = context.getRequiredTestInstances(); Object target = testInstances.findInstance(this.testClass).orElseThrow( () -> new JUnitException("Failed to find instance for method: " + method.toGenericString())); executableInvoker.invoke(method, target, context, registry, ReflectiveInterceptorCall.ofVoidMethod(interceptorCall)); } } ClassExtensionContext.java000066400000000000000000000064331455764576500360650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.Node; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * @since 5.0 */ final class ClassExtensionContext extends AbstractExtensionContext { private final Lifecycle lifecycle; private final ThrowableCollector throwableCollector; private TestInstances testInstances; /** * Create a new {@code ClassExtensionContext} with {@link Lifecycle#PER_METHOD}. * * @see #ClassExtensionContext(ExtensionContext, EngineExecutionListener, ClassBasedTestDescriptor, * Lifecycle, JupiterConfiguration, ThrowableCollector, ExecutableInvoker) */ ClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, ClassBasedTestDescriptor testDescriptor, JupiterConfiguration configuration, ThrowableCollector throwableCollector, ExecutableInvoker executableInvoker) { this(parent, engineExecutionListener, testDescriptor, Lifecycle.PER_METHOD, configuration, throwableCollector, executableInvoker); } ClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, ClassBasedTestDescriptor testDescriptor, Lifecycle lifecycle, JupiterConfiguration configuration, ThrowableCollector throwableCollector, ExecutableInvoker executableInvoker) { super(parent, engineExecutionListener, testDescriptor, configuration, executableInvoker); this.lifecycle = lifecycle; this.throwableCollector = throwableCollector; } @Override public Optional getElement() { return Optional.of(getTestDescriptor().getTestClass()); } @Override public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } @Override public Optional getTestInstanceLifecycle() { return Optional.of(this.lifecycle); } @Override public Optional getTestInstance() { return getTestInstances().map(TestInstances::getInnermostInstance); } @Override public Optional getTestInstances() { return Optional.ofNullable(testInstances); } void setTestInstances(TestInstances testInstances) { this.testInstances = testInstances; } @Override public Optional getTestMethod() { return Optional.empty(); } @Override public Optional getExecutionException() { return Optional.ofNullable(this.throwableCollector.getThrowable()); } @Override protected Node.ExecutionMode getPlatformExecutionMode() { return getTestDescriptor().getExecutionMode(); } } ClassTestDescriptor.java000066400000000000000000000054461455764576500355250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.DisplayNameUtils.createDisplayNameSupplierForClass; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistrar; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * {@link TestDescriptor} for tests based on Java classes. * *

Default Display Names

* *

The default display name for a top-level or nested static test class is * the fully qualified name of the class with the package name and leading dot * (".") removed. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class ClassTestDescriptor extends ClassBasedTestDescriptor { public static final String SEGMENT_TYPE = "class"; public ClassTestDescriptor(UniqueId uniqueId, Class testClass, JupiterConfiguration configuration) { super(uniqueId, testClass, createDisplayNameSupplierForClass(testClass, configuration), configuration); } // --- TestDescriptor ------------------------------------------------------ @Override public Set getTags() { // return modifiable copy return new LinkedHashSet<>(this.tags); } @Override public List> getEnclosingTestClasses() { return emptyList(); } // --- Node ---------------------------------------------------------------- @Override public ExecutionMode getExecutionMode() { return getExplicitExecutionMode().orElseGet( () -> JupiterTestDescriptor.toExecutionMode(configuration.getDefaultClassesExecutionMode())); } @Override protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext, ThrowableCollector throwableCollector) { return instantiateTestClass(Optional.empty(), registry, extensionContext); } } DefaultDynamicTestInvocationContext.java000066400000000000000000000015631455764576500407050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import org.junit.jupiter.api.extension.DynamicTestInvocationContext; import org.junit.jupiter.api.function.Executable; /** * Default implementation of the {@link DynamicTestInvocationContext} API. * * @since 5.8 */ class DefaultDynamicTestInvocationContext implements DynamicTestInvocationContext { private final Executable executable; DefaultDynamicTestInvocationContext(Executable executable) { this.executable = executable; } @Override public Executable getExecutable() { return this.executable; } } DefaultTestInstanceFactoryContext.java000066400000000000000000000024561455764576500403650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.util.Optional; import org.junit.jupiter.api.extension.TestInstanceFactoryContext; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of the {@link TestInstanceFactoryContext} API. * * @since 5.3 */ class DefaultTestInstanceFactoryContext implements TestInstanceFactoryContext { private final Class testClass; private final Optional outerInstance; DefaultTestInstanceFactoryContext(Class testClass, Optional outerInstance) { this.testClass = testClass; this.outerInstance = outerInstance; } @Override public Class getTestClass() { return this.testClass; } @Override public Optional getOuterInstance() { return this.outerInstance; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("testClass", this.testClass) .append("outerInstance", this.outerInstance) .toString(); // @formatter:on } } DisplayNameUtils.java000066400000000000000000000130601455764576500347770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.DisplayNameGenerator.IndicativeSentences; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.DisplayNameGenerator.Simple; import org.junit.jupiter.api.DisplayNameGenerator.Standard; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; /** * Collection of utilities for working with display names. * * @since 5.4 * @see DisplayName * @see DisplayNameGenerator * @see DisplayNameGeneration */ final class DisplayNameUtils { private static final Logger logger = LoggerFactory.getLogger(DisplayNameUtils.class); /** * Pre-defined standard display name generator instance. */ private static final DisplayNameGenerator standardGenerator = DisplayNameGenerator.getDisplayNameGenerator( Standard.class); /** * Pre-defined simple display name generator instance. */ private static final DisplayNameGenerator simpleGenerator = DisplayNameGenerator.getDisplayNameGenerator( Simple.class); /** * Pre-defined display name generator instance replacing underscores. */ private static final DisplayNameGenerator replaceUnderscoresGenerator = DisplayNameGenerator.getDisplayNameGenerator( ReplaceUnderscores.class); /** * Pre-defined display name generator instance producing indicative sentences. */ private static final DisplayNameGenerator indicativeSentencesGenerator = DisplayNameGenerator.getDisplayNameGenerator( IndicativeSentences.class); static String determineDisplayName(AnnotatedElement element, Supplier displayNameSupplier) { Preconditions.notNull(element, "Annotated element must not be null"); Optional displayNameAnnotation = findAnnotation(element, DisplayName.class); if (displayNameAnnotation.isPresent()) { String displayName = displayNameAnnotation.get().value().trim(); // TODO [#242] Replace logging with precondition check once we have a proper mechanism for // handling validation exceptions during the TestEngine discovery phase. if (StringUtils.isBlank(displayName)) { logger.warn(() -> String.format( "Configuration error: @DisplayName on [%s] must be declared with a non-empty value.", element)); } else { return displayName; } } // else let a 'DisplayNameGenerator' generate a display name return displayNameSupplier.get(); } static String determineDisplayNameForMethod(Class testClass, Method testMethod, JupiterConfiguration configuration) { return determineDisplayName(testMethod, createDisplayNameSupplierForMethod(testClass, testMethod, configuration)); } static Supplier createDisplayNameSupplierForClass(Class testClass, JupiterConfiguration configuration) { return createDisplayNameSupplier(testClass, configuration, generator -> generator.generateDisplayNameForClass(testClass)); } static Supplier createDisplayNameSupplierForNestedClass(Class testClass, JupiterConfiguration configuration) { return createDisplayNameSupplier(testClass, configuration, generator -> generator.generateDisplayNameForNestedClass(testClass)); } private static Supplier createDisplayNameSupplierForMethod(Class testClass, Method testMethod, JupiterConfiguration configuration) { return createDisplayNameSupplier(testClass, configuration, generator -> generator.generateDisplayNameForMethod(testClass, testMethod)); } private static Supplier createDisplayNameSupplier(Class testClass, JupiterConfiguration configuration, Function generatorFunction) { return () -> findDisplayNameGenerator(testClass) // .map(generatorFunction) // .orElseGet(() -> generatorFunction.apply(configuration.getDefaultDisplayNameGenerator())); } private static Optional findDisplayNameGenerator(Class testClass) { Preconditions.notNull(testClass, "Test class must not be null"); return AnnotationUtils.findAnnotation(testClass, DisplayNameGeneration.class, true) // .map(DisplayNameGeneration::value) // .map(displayNameGeneratorClass -> { if (displayNameGeneratorClass == Standard.class) { return standardGenerator; } if (displayNameGeneratorClass == Simple.class) { return simpleGenerator; } if (displayNameGeneratorClass == ReplaceUnderscores.class) { return replaceUnderscoresGenerator; } if (displayNameGeneratorClass == IndicativeSentences.class) { return indicativeSentencesGenerator; } return ReflectionUtils.newInstance(displayNameGeneratorClass); }); } } DynamicContainerTestDescriptor.java000066400000000000000000000051261455764576500377020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor.createDynamicDescriptor; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; /** * {@link TestDescriptor} for a {@link DynamicContainer}. * * @since 5.0 */ class DynamicContainerTestDescriptor extends DynamicNodeTestDescriptor { private final DynamicContainer dynamicContainer; private final TestSource testSource; private final DynamicDescendantFilter dynamicDescendantFilter; DynamicContainerTestDescriptor(UniqueId uniqueId, int index, DynamicContainer dynamicContainer, TestSource testSource, DynamicDescendantFilter dynamicDescendantFilter, JupiterConfiguration configuration) { super(uniqueId, index, dynamicContainer, testSource, configuration); this.dynamicContainer = dynamicContainer; this.testSource = testSource; this.dynamicDescendantFilter = dynamicDescendantFilter; } @Override public Type getType() { return Type.CONTAINER; } @Override public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) throws Exception { AtomicInteger index = new AtomicInteger(1); try (Stream children = dynamicContainer.getChildren()) { // @formatter:off children.map(child -> { Preconditions.notNull(child, "individual dynamic node must not be null"); return toDynamicDescriptor(index.getAndIncrement(), child); }) .filter(Optional::isPresent) .map(Optional::get) .forEachOrdered(dynamicTestExecutor::execute); // @formatter:on } return context; } private Optional toDynamicDescriptor(int index, DynamicNode childNode) { return createDynamicDescriptor(this, childNode, index, testSource, dynamicDescendantFilter, configuration); } } DynamicDescendantFilter.java000066400000000000000000000050241455764576500362740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.HashSet; import java.util.Set; import java.util.function.BiPredicate; import org.apiguardian.api.API; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; /** * Filter for dynamic descendants of {@link TestDescriptor TestDescriptors} that * implement {@link Filterable}. * * @since 5.1 * @see Filterable */ @API(status = INTERNAL, since = "5.1") public class DynamicDescendantFilter implements BiPredicate { private final Set allowedUniqueIds = new HashSet<>(); private final Set allowedIndices = new HashSet<>(); private Mode mode = Mode.EXPLICIT; public void allowUniqueIdPrefix(UniqueId uniqueId) { if (this.mode == Mode.EXPLICIT) { this.allowedUniqueIds.add(uniqueId); } } public void allowIndex(Set indices) { if (this.mode == Mode.EXPLICIT) { this.allowedIndices.addAll(indices); } } public void allowAll() { this.mode = Mode.ALLOW_ALL; this.allowedUniqueIds.clear(); this.allowedIndices.clear(); } @Override public boolean test(UniqueId uniqueId, Integer index) { return isEverythingAllowed() // || isUniqueIdAllowed(uniqueId) // || allowedIndices.contains(index); } private boolean isEverythingAllowed() { return allowedUniqueIds.isEmpty() && allowedIndices.isEmpty(); } private boolean isUniqueIdAllowed(UniqueId uniqueId) { return allowedUniqueIds.stream().anyMatch(allowedUniqueId -> isPrefixOrViceVersa(uniqueId, allowedUniqueId)); } private boolean isPrefixOrViceVersa(UniqueId currentUniqueId, UniqueId allowedUniqueId) { return allowedUniqueId.hasPrefix(currentUniqueId) || currentUniqueId.hasPrefix(allowedUniqueId); } public DynamicDescendantFilter withoutIndexFiltering() { return new WithoutIndexFiltering(); } private enum Mode { EXPLICIT, ALLOW_ALL } private class WithoutIndexFiltering extends DynamicDescendantFilter { @Override public boolean test(UniqueId uniqueId, Integer index) { return isEverythingAllowed() || isUniqueIdAllowed(uniqueId); } @Override public DynamicDescendantFilter withoutIndexFiltering() { return this; } } } DynamicExtensionContext.java000066400000000000000000000037761455764576500364130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.Node; class DynamicExtensionContext extends AbstractExtensionContext { DynamicExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, DynamicNodeTestDescriptor testDescriptor, JupiterConfiguration configuration, ExecutableInvoker executableInvoker) { super(parent, engineExecutionListener, testDescriptor, configuration, executableInvoker); } @Override public Optional getElement() { return Optional.empty(); } @Override public Optional> getTestClass() { return Optional.empty(); } @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); } @Override public Optional getTestInstance() { return Optional.empty(); } @Override public Optional getTestInstances() { return Optional.empty(); } @Override public Optional getTestMethod() { return Optional.empty(); } @Override public Optional getExecutionException() { return Optional.empty(); } @Override protected Node.ExecutionMode getPlatformExecutionMode() { return getTestDescriptor().getExecutionMode(); } } DynamicNodeTestDescriptor.java000066400000000000000000000036631455764576500366510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; /** * Base {@link TestDescriptor} for a {@link DynamicNode}. * * @since 5.0.3 */ abstract class DynamicNodeTestDescriptor extends JupiterTestDescriptor { private final int index; DynamicNodeTestDescriptor(UniqueId uniqueId, int index, DynamicNode dynamicNode, TestSource testSource, JupiterConfiguration configuration) { super(uniqueId, dynamicNode.getDisplayName(), testSource, configuration); this.index = index; } @Override public String getLegacyReportingName() { // @formatter:off return getParent() .map(TestDescriptor::getLegacyReportingName) .orElseGet(this::getDisplayName) + "[" + index + "]"; // @formatter:on } @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { DynamicExtensionContext extensionContext = new DynamicExtensionContext(context.getExtensionContext(), context.getExecutionListener(), this, context.getConfiguration(), new DefaultExecutableInvoker(context)); // @formatter:off return context.extend() .withExtensionContext(extensionContext) .build(); // @formatter:on } @Override public SkipResult shouldBeSkipped(JupiterEngineExecutionContext context) { return SkipResult.doNotSkip(); } } DynamicTestTestDescriptor.java000066400000000000000000000057101455764576500366760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.extension.DynamicTestInvocationContext; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.InvocationInterceptorChain; import org.junit.jupiter.engine.execution.InvocationInterceptorChain.InterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; /** * {@link TestDescriptor} for a {@link DynamicTest}. * * @since 5.0 */ class DynamicTestTestDescriptor extends DynamicNodeTestDescriptor { private static final InvocationInterceptorChain interceptorChain = new InvocationInterceptorChain(); private DynamicTest dynamicTest; DynamicTestTestDescriptor(UniqueId uniqueId, int index, DynamicTest dynamicTest, TestSource source, JupiterConfiguration configuration) { super(uniqueId, index, dynamicTest, source, configuration); this.dynamicTest = dynamicTest; } @Override public Type getType() { return Type.TEST; } @Override public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { InvocationInterceptor.Invocation invocation = () -> { dynamicTest.getExecutable().execute(); return null; }; DynamicTestInvocationContext dynamicTestInvocationContext = new DefaultDynamicTestInvocationContext( dynamicTest.getExecutable()); ExtensionContext extensionContext = context.getExtensionContext(); ExtensionRegistry extensionRegistry = context.getExtensionRegistry(); interceptorChain.invoke(invocation, extensionRegistry, InterceptorCall.ofVoid( (interceptor, wrappedInvocation) -> interceptor.interceptDynamicTest(wrappedInvocation, dynamicTestInvocationContext, extensionContext))); return context; } /** * Avoid an {@link OutOfMemoryError} by releasing the reference to this * descriptor's {@link DynamicTest} which holds a reference to the user-supplied * {@link Executable} which may potentially consume large amounts of memory * on the heap. * * @since 5.5 * @see Issue 1865 */ @Override public void after(JupiterEngineExecutionContext context) throws Exception { super.after(context); this.dynamicTest = null; } } ExtensionUtils.java000066400000000000000000000172771455764576500345630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.util.ReflectionUtils.getDeclaredConstructor; import static org.junit.platform.commons.util.ReflectionUtils.streamFields; import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; import java.util.stream.Stream; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.engine.extension.ExtensionRegistrar; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * Collection of utilities for working with extensions and the extension registry. * * @since 5.1 * @see ExtensionRegistrar * @see MutableExtensionRegistry * @see ExtendWith * @see RegisterExtension */ final class ExtensionUtils { private ExtensionUtils() { /* no-op */ } /** * Populate a new {@link MutableExtensionRegistry} from extension types declared via * {@link ExtendWith @ExtendWith} on the supplied {@link AnnotatedElement}. * * @param parentRegistry the parent extension registry to set in the newly * created registry; never {@code null} * @param annotatedElement the annotated element on which to search for * declarations of {@code @ExtendWith}; never {@code null} * * @return the new extension registry; never {@code null} * @since 5.0 */ static MutableExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation( MutableExtensionRegistry parentRegistry, AnnotatedElement annotatedElement) { Preconditions.notNull(parentRegistry, "Parent ExtensionRegistry must not be null"); Preconditions.notNull(annotatedElement, "AnnotatedElement must not be null"); return MutableExtensionRegistry.createRegistryFrom(parentRegistry, streamExtensionTypes(annotatedElement)); } /** * Register extensions using the supplied registrar from fields in the supplied * class that are annotated with {@link ExtendWith @ExtendWith} or * {@link RegisterExtension @RegisterExtension}. * *

The extensions will be sorted according to {@link Order @Order} semantics * prior to registration. * * @param registrar the registrar with which to register the extensions; never {@code null} * @param clazz the class or interface in which to find the fields; never {@code null} * @param instance the instance of the supplied class; may be {@code null} * when searching for {@code static} fields in the class */ static void registerExtensionsFromFields(ExtensionRegistrar registrar, Class clazz, Object instance) { Preconditions.notNull(registrar, "ExtensionRegistrar must not be null"); Preconditions.notNull(clazz, "Class must not be null"); Predicate predicate = (instance == null ? ReflectionUtils::isStatic : ReflectionUtils::isNotStatic); streamFields(clazz, predicate, TOP_DOWN)// .sorted(orderComparator)// .forEach(field -> { List> extensionTypes = streamExtensionTypes(field).collect(toList()); boolean isExtendWithPresent = !extensionTypes.isEmpty(); boolean isRegisterExtensionPresent = isAnnotated(field, RegisterExtension.class); if (isExtendWithPresent) { extensionTypes.forEach(registrar::registerExtension); } if (isRegisterExtensionPresent) { tryToReadFieldValue(field, instance).ifSuccess(value -> { Preconditions.condition(value instanceof Extension, () -> String.format( "Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.", field, (value != null ? value.getClass().getName() : null), Extension.class.getName())); if (isExtendWithPresent) { Class valueType = value.getClass(); extensionTypes.forEach(extensionType -> { Preconditions.condition(!extensionType.equals(valueType), () -> String.format("Failed to register extension via field [%s]. " + "The field registers an extension of type [%s] via @RegisterExtension and @ExtendWith, " + "but only one registration of a given extension type is permitted.", field, valueType.getName())); }); } registrar.registerExtension((Extension) value, field); }); } }); } /** * Register extensions using the supplied registrar from parameters in the * declared constructor of the supplied class that are annotated with * {@link ExtendWith @ExtendWith}. * * @param registrar the registrar with which to register the extensions; never {@code null} * @param clazz the class in which to find the declared constructor; never {@code null} * @since 5.8 */ static void registerExtensionsFromConstructorParameters(ExtensionRegistrar registrar, Class clazz) { registerExtensionsFromExecutableParameters(registrar, getDeclaredConstructor(clazz)); } /** * Register extensions using the supplied registrar from parameters in the * supplied {@link Executable} (i.e., a {@link java.lang.reflect.Constructor} * or {@link java.lang.reflect.Method}) that are annotated with * {@link ExtendWith @ExtendWith}. * * @param registrar the registrar with which to register the extensions; never {@code null} * @param executable the constructor or method whose parameters should be searched; never {@code null} * @since 5.8 */ static void registerExtensionsFromExecutableParameters(ExtensionRegistrar registrar, Executable executable) { Preconditions.notNull(registrar, "ExtensionRegistrar must not be null"); Preconditions.notNull(executable, "Executable must not be null"); AtomicInteger index = new AtomicInteger(); // @formatter:off Arrays.stream(executable.getParameters()) .map(parameter -> findRepeatableAnnotations(parameter, index.getAndIncrement(), ExtendWith.class)) .flatMap(ExtensionUtils::streamExtensionTypes) .forEach(registrar::registerExtension); // @formatter:on } /** * @since 5.8 */ private static Stream> streamExtensionTypes(AnnotatedElement annotatedElement) { return streamExtensionTypes(findRepeatableAnnotations(annotatedElement, ExtendWith.class)); } /** * @since 5.8 */ private static Stream> streamExtensionTypes(List extendWithAnnotations) { return extendWithAnnotations.stream().map(ExtendWith::value).flatMap(Arrays::stream); } /** * @since 5.4 */ private static final Comparator orderComparator = // Comparator.comparingInt(ExtensionUtils::getOrder); /** * @since 5.4 */ private static int getOrder(Field field) { return findAnnotation(field, Order.class).map(Order::value).orElse(Order.DEFAULT); } } Filterable.java000066400000000000000000000015011455764576500336160ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; /** * {@code Filterable} is implemented by * {@link org.junit.platform.engine.TestDescriptor TestDescriptors} that may * register dynamic tests during execution and support selective test execution. * * @since 5.1 * @see DynamicDescendantFilter */ @API(status = INTERNAL, since = "5.1") public interface Filterable { DynamicDescendantFilter getDynamicDescendantFilter(); } JupiterEngineDescriptor.java000066400000000000000000000051201455764576500363550ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.toExecutionMode; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.engine.support.hierarchical.Node; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class JupiterEngineDescriptor extends EngineDescriptor implements Node { public static final String ENGINE_ID = "junit-jupiter"; private final JupiterConfiguration configuration; public JupiterEngineDescriptor(UniqueId uniqueId, JupiterConfiguration configuration) { super(uniqueId, "JUnit Jupiter"); this.configuration = configuration; } public JupiterConfiguration getConfiguration() { return configuration; } @Override public ExecutionMode getExecutionMode() { return toExecutionMode(configuration.getDefaultExecutionMode()); } @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions( context.getConfiguration()); EngineExecutionListener executionListener = context.getExecutionListener(); ExecutableInvoker executableInvoker = new DefaultExecutableInvoker(context); ExtensionContext extensionContext = new JupiterEngineExtensionContext(executionListener, this, context.getConfiguration(), executableInvoker); // @formatter:off return context.extend() .withExtensionRegistry(extensionRegistry) .withExtensionContext(extensionContext) .build(); // @formatter:on } @Override public void cleanUp(JupiterEngineExecutionContext context) throws Exception { context.close(); } } JupiterEngineExtensionContext.java000066400000000000000000000037141455764576500375670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.Node; /** * @since 5.0 */ final class JupiterEngineExtensionContext extends AbstractExtensionContext { JupiterEngineExtensionContext(EngineExecutionListener engineExecutionListener, JupiterEngineDescriptor testDescriptor, JupiterConfiguration configuration, ExecutableInvoker executableInvoker) { super(null, engineExecutionListener, testDescriptor, configuration, executableInvoker); } @Override public Optional getElement() { return Optional.empty(); } @Override public Optional> getTestClass() { return Optional.empty(); } @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); } @Override public Optional getTestInstance() { return Optional.empty(); } @Override public Optional getTestInstances() { return Optional.empty(); } @Override public Optional getTestMethod() { return Optional.empty(); } @Override public Optional getExecutionException() { return Optional.empty(); } @Override protected Node.ExecutionMode getPlatformExecutionMode() { return getTestDescriptor().getExecutionMode(); } } JupiterTestDescriptor.java000066400000000000000000000211551455764576500360750ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.DisplayNameUtils.determineDisplayName; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import java.lang.reflect.AnnotatedElement; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ResourceAccessMode; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.ConditionEvaluator; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; import org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode; import org.junit.platform.engine.support.hierarchical.Node; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public abstract class JupiterTestDescriptor extends AbstractTestDescriptor implements Node { private static final Logger logger = LoggerFactory.getLogger(JupiterTestDescriptor.class); private static final ConditionEvaluator conditionEvaluator = new ConditionEvaluator(); final JupiterConfiguration configuration; JupiterTestDescriptor(UniqueId uniqueId, AnnotatedElement element, Supplier displayNameSupplier, TestSource source, JupiterConfiguration configuration) { this(uniqueId, determineDisplayName(element, displayNameSupplier), source, configuration); } JupiterTestDescriptor(UniqueId uniqueId, String displayName, TestSource source, JupiterConfiguration configuration) { super(uniqueId, displayName, source); this.configuration = configuration; } // --- TestDescriptor ------------------------------------------------------ static Set getTags(AnnotatedElement element) { // @formatter:off return findRepeatableAnnotations(element, Tag.class).stream() .map(Tag::value) .filter(tag -> { boolean isValid = TestTag.isValid(tag); if (!isValid) { // TODO [#242] Replace logging with precondition check once we have a proper mechanism for // handling validation exceptions during the TestEngine discovery phase. // // As an alternative to a precondition check here, we could catch any // PreconditionViolationException thrown by TestTag::create. logger.warn(() -> String.format( "Configuration error: invalid tag syntax in @Tag(\"%s\") declaration on [%s]. Tag will be ignored.", tag, element)); } return isValid; }) .map(TestTag::create) .collect(collectingAndThen(toCollection(LinkedHashSet::new), Collections::unmodifiableSet)); // @formatter:on } /** * Invoke exception handlers for the supplied {@code Throwable} one-by-one * until none are left or the throwable to handle has been swallowed. */ void invokeExecutionExceptionHandlers(Class handlerType, ExtensionRegistry registry, Throwable throwable, ExceptionHandlerInvoker handlerInvoker) { List extensions = registry.getExtensions(handlerType); Collections.reverse(extensions); invokeExecutionExceptionHandlers(extensions, throwable, handlerInvoker); } private void invokeExecutionExceptionHandlers(List exceptionHandlers, Throwable throwable, ExceptionHandlerInvoker handlerInvoker) { // No handlers left? if (exceptionHandlers.isEmpty()) { ExceptionUtils.throwAsUncheckedException(throwable); } try { // Invoke next available handler handlerInvoker.invoke(exceptionHandlers.remove(0), throwable); } catch (Throwable handledThrowable) { UnrecoverableExceptions.rethrowIfUnrecoverable(handledThrowable); invokeExecutionExceptionHandlers(exceptionHandlers, handledThrowable, handlerInvoker); } } // --- Node ---------------------------------------------------------------- @Override public ExecutionMode getExecutionMode() { Optional executionMode = getExplicitExecutionMode(); if (executionMode.isPresent()) { return executionMode.get(); } Optional parent = getParent(); while (parent.isPresent() && parent.get() instanceof JupiterTestDescriptor) { JupiterTestDescriptor jupiterParent = (JupiterTestDescriptor) parent.get(); executionMode = jupiterParent.getExplicitExecutionMode(); if (executionMode.isPresent()) { return executionMode.get(); } executionMode = jupiterParent.getDefaultChildExecutionMode(); if (executionMode.isPresent()) { return executionMode.get(); } parent = jupiterParent.getParent(); } return toExecutionMode(configuration.getDefaultExecutionMode()); } Optional getExplicitExecutionMode() { return Optional.empty(); } Optional getDefaultChildExecutionMode() { return Optional.empty(); } Optional getExecutionModeFromAnnotation(AnnotatedElement element) { // @formatter:off return findAnnotation(element, Execution.class) .map(Execution::value) .map(JupiterTestDescriptor::toExecutionMode); // @formatter:on } public static ExecutionMode toExecutionMode(org.junit.jupiter.api.parallel.ExecutionMode mode) { switch (mode) { case CONCURRENT: return ExecutionMode.CONCURRENT; case SAME_THREAD: return ExecutionMode.SAME_THREAD; } throw new JUnitException("Unknown ExecutionMode: " + mode); } Set getExclusiveResourcesFromAnnotation(AnnotatedElement element) { // @formatter:off return findRepeatableAnnotations(element, ResourceLock.class).stream() .map(resource -> new ExclusiveResource(resource.value(), toLockMode(resource.mode()))) .collect(toSet()); // @formatter:on } private static LockMode toLockMode(ResourceAccessMode mode) { switch (mode) { case READ: return LockMode.READ; case READ_WRITE: return LockMode.READ_WRITE; } throw new JUnitException("Unknown ResourceAccessMode: " + mode); } @Override public SkipResult shouldBeSkipped(JupiterEngineExecutionContext context) throws Exception { context.getThrowableCollector().assertEmpty(); ConditionEvaluationResult evaluationResult = conditionEvaluator.evaluate(context.getExtensionRegistry(), context.getConfiguration(), context.getExtensionContext()); return toSkipResult(evaluationResult); } private SkipResult toSkipResult(ConditionEvaluationResult evaluationResult) { if (evaluationResult.isDisabled()) { return SkipResult.skip(evaluationResult.getReason().orElse("")); } return SkipResult.doNotSkip(); } /** * Must be overridden and return a new context so cleanUp() does not accidentally close the parent context. */ @Override public abstract JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception; @Override public void cleanUp(JupiterEngineExecutionContext context) throws Exception { context.close(); } /** * @since 5.5 */ @FunctionalInterface interface ExceptionHandlerInvoker { /** * Invoke the supplied {@code exceptionHandler} with the supplied {@code throwable}. */ void invoke(E exceptionHandler, Throwable throwable) throws Throwable; } } LifecycleMethodUtils.java000066400000000000000000000077041455764576500356410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotatedMethods; import static org.junit.platform.commons.util.ReflectionUtils.returnsVoid; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode; /** * Collection of utilities for working with test lifecycle methods. * * @since 5.0 */ final class LifecycleMethodUtils { private LifecycleMethodUtils() { /* no-op */ } static List findBeforeAllMethods(Class testClass, boolean requireStatic) { return findMethodsAndAssertStaticAndNonPrivate(testClass, requireStatic, BeforeAll.class, HierarchyTraversalMode.TOP_DOWN); } static List findAfterAllMethods(Class testClass, boolean requireStatic) { return findMethodsAndAssertStaticAndNonPrivate(testClass, requireStatic, AfterAll.class, HierarchyTraversalMode.BOTTOM_UP); } static List findBeforeEachMethods(Class testClass) { return findMethodsAndAssertNonStaticAndNonPrivate(testClass, BeforeEach.class, HierarchyTraversalMode.TOP_DOWN); } static List findAfterEachMethods(Class testClass) { return findMethodsAndAssertNonStaticAndNonPrivate(testClass, AfterEach.class, HierarchyTraversalMode.BOTTOM_UP); } private static List findMethodsAndAssertStaticAndNonPrivate(Class testClass, boolean requireStatic, Class annotationType, HierarchyTraversalMode traversalMode) { List methods = findMethodsAndCheckVoidReturnType(testClass, annotationType, traversalMode); if (requireStatic) { methods.forEach(method -> assertStatic(annotationType, method)); } return methods; } private static List findMethodsAndAssertNonStaticAndNonPrivate(Class testClass, Class annotationType, HierarchyTraversalMode traversalMode) { List methods = findMethodsAndCheckVoidReturnType(testClass, annotationType, traversalMode); methods.forEach(method -> assertNonStatic(annotationType, method)); return methods; } private static List findMethodsAndCheckVoidReturnType(Class testClass, Class annotationType, HierarchyTraversalMode traversalMode) { List methods = findAnnotatedMethods(testClass, annotationType, traversalMode); methods.forEach(method -> assertVoid(annotationType, method)); return methods; } private static void assertStatic(Class annotationType, Method method) { if (ReflectionUtils.isNotStatic(method)) { throw new JUnitException(String.format( "@%s method '%s' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).", annotationType.getSimpleName(), method.toGenericString())); } } private static void assertNonStatic(Class annotationType, Method method) { if (ReflectionUtils.isStatic(method)) { throw new JUnitException(String.format("@%s method '%s' must not be static.", annotationType.getSimpleName(), method.toGenericString())); } } private static void assertVoid(Class annotationType, Method method) { if (!returnsVoid(method)) { throw new JUnitException(String.format("@%s method '%s' must not return a value.", annotationType.getSimpleName(), method.toGenericString())); } } } MethodBasedTestDescriptor.java000066400000000000000000000117271455764576500366360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.DisplayNameUtils.determineDisplayNameForMethod; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.lang.reflect.Method; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestWatcher; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; /** * Base class for {@link TestDescriptor TestDescriptors} based on Java methods. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public abstract class MethodBasedTestDescriptor extends JupiterTestDescriptor { private static final Logger logger = LoggerFactory.getLogger(MethodBasedTestDescriptor.class); private final Class testClass; private final Method testMethod; /** * Set of method-level tags; does not contain tags from parent. */ private final Set tags; MethodBasedTestDescriptor(UniqueId uniqueId, Class testClass, Method testMethod, JupiterConfiguration configuration) { this(uniqueId, determineDisplayNameForMethod(testClass, testMethod, configuration), testClass, testMethod, configuration); } MethodBasedTestDescriptor(UniqueId uniqueId, String displayName, Class testClass, Method testMethod, JupiterConfiguration configuration) { super(uniqueId, displayName, MethodSource.from(testClass, testMethod), configuration); this.testClass = Preconditions.notNull(testClass, "Class must not be null"); this.testMethod = testMethod; this.tags = getTags(testMethod); } @Override public final Set getTags() { // return modifiable copy Set allTags = new LinkedHashSet<>(this.tags); getParent().ifPresent(parentDescriptor -> allTags.addAll(parentDescriptor.getTags())); return allTags; } @Override public Set getExclusiveResources() { return getExclusiveResourcesFromAnnotation(getTestMethod()); } @Override protected Optional getExplicitExecutionMode() { return getExecutionModeFromAnnotation(getTestMethod()); } public final Class getTestClass() { return this.testClass; } public final Method getTestMethod() { return this.testMethod; } @Override public String getLegacyReportingName() { return String.format("%s(%s)", testMethod.getName(), ClassUtils.nullSafeToString(Class::getSimpleName, testMethod.getParameterTypes())); } /** * Invoke {@link TestWatcher#testDisabled(ExtensionContext, Optional)} on each * registered {@link TestWatcher}, in registration order. * * @since 5.4 */ @Override public void nodeSkipped(JupiterEngineExecutionContext context, TestDescriptor descriptor, SkipResult result) { if (context != null) { invokeTestWatchers(context, false, watcher -> watcher.testDisabled(context.getExtensionContext(), result.getReason())); } } /** * @since 5.4 */ protected void invokeTestWatchers(JupiterEngineExecutionContext context, boolean reverseOrder, Consumer callback) { List watchers = context.getExtensionRegistry().getExtensions(TestWatcher.class); Consumer action = watcher -> { try { callback.accept(watcher); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); ExtensionContext extensionContext = context.getExtensionContext(); logger.warn(throwable, () -> String.format("Failed to invoke TestWatcher [%s] for method [%s] with display name [%s]", watcher.getClass().getName(), ReflectionUtils.getFullyQualifiedMethodName(extensionContext.getRequiredTestClass(), extensionContext.getRequiredTestMethod()), getDisplayName())); } }; if (reverseOrder) { forEachInReverseOrder(watchers, action); } else { watchers.forEach(action); } } } MethodExtensionContext.java000066400000000000000000000051561455764576500362410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.Node; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * @since 5.0 */ final class MethodExtensionContext extends AbstractExtensionContext { private final ThrowableCollector throwableCollector; private TestInstances testInstances; MethodExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, TestMethodTestDescriptor testDescriptor, JupiterConfiguration configuration, ThrowableCollector throwableCollector, ExecutableInvoker executableInvoker) { super(parent, engineExecutionListener, testDescriptor, configuration, executableInvoker); this.throwableCollector = throwableCollector; } @Override public Optional getElement() { return Optional.of(getTestDescriptor().getTestMethod()); } @Override public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } @Override public Optional getTestInstanceLifecycle() { return getParent().flatMap(ExtensionContext::getTestInstanceLifecycle); } @Override public Optional getTestInstance() { return getTestInstances().map(TestInstances::getInnermostInstance); } @Override public Optional getTestInstances() { return Optional.ofNullable(this.testInstances); } void setTestInstances(TestInstances testInstances) { this.testInstances = testInstances; } @Override public Optional getTestMethod() { return Optional.of(getTestDescriptor().getTestMethod()); } @Override public Optional getExecutionException() { return Optional.ofNullable(this.throwableCollector.getThrowable()); } @Override protected Node.ExecutionMode getPlatformExecutionMode() { return getTestDescriptor().getExecutionMode(); } } MethodSourceSupport.java000066400000000000000000000053061455764576500355520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.net.URI; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.support.descriptor.MethodSource; /** * Jupiter internal support for creating {@link MethodSource} from {@link URI}. * * @since 5.5 * @see MethodSource * @see MethodSelector */ class MethodSourceSupport { static final String METHOD_SCHEME = "method"; /** * Create a new {@code MethodSource} from the supplied {@link URI}. * *

The supplied {@link URI} should be of the form {@code method:} * where FQMN is the fully qualified method name. See * {@link DiscoverySelectors#selectMethod(String)} for the supported formats. * *

The {@link URI#getSchemeSpecificPart() scheme-specific part} * component of the {@code URI} will be used as fully qualified class name. * The {@linkplain URI#getFragment() fragment} component of the {@code URI} * will be used to retrieve the method name and method parameter types. * * @param uri the {@code URI} for the method; never {@code null} * @return a new {@code MethodSource}; never {@code null} * @since 5.5 * @see #METHOD_SCHEME * @see DiscoverySelectors#selectMethod(String) */ static MethodSource from(URI uri) { Preconditions.notNull(uri, "URI must not be null"); Preconditions.condition(METHOD_SCHEME.equals(uri.getScheme()), () -> "URI [" + uri + "] must have [" + METHOD_SCHEME + "] scheme"); String schemeSpecificPart = Preconditions.notNull(uri.getSchemeSpecificPart(), () -> "Invalid method URI (scheme-specific part must not be null). Please consult the Javadoc of " + DiscoverySelectors.class.getName() + "#selectMethod(String) for details on the supported formats."); String fragment = Preconditions.notNull(uri.getFragment(), () -> "Invalid method URI (fragment must not be null). Please consult the Javadoc of " + DiscoverySelectors.class.getName() + "#selectMethod(String) for details on the supported formats."); String fullyQualifiedMethodName = schemeSpecificPart + "#" + fragment; String[] methodSpec = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); return MethodSource.from(methodSpec[0], methodSpec[1], methodSpec[2]); } } NestedClassTestDescriptor.java000066400000000000000000000067701455764576500366710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.DisplayNameUtils.createDisplayNameSupplierForNestedClass; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistrar; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * {@link TestDescriptor} for tests based on nested (but not static) Java classes. * *

Default Display Names

* *

The default display name for a non-static nested test class is the simple * name of the class. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class NestedClassTestDescriptor extends ClassBasedTestDescriptor { public static final String SEGMENT_TYPE = "nested-class"; public NestedClassTestDescriptor(UniqueId uniqueId, Class testClass, JupiterConfiguration configuration) { super(uniqueId, testClass, createDisplayNameSupplierForNestedClass(testClass, configuration), configuration); } // --- TestDescriptor ------------------------------------------------------ @Override public final Set getTags() { // return modifiable copy Set allTags = new LinkedHashSet<>(this.tags); getParent().ifPresent(parentDescriptor -> allTags.addAll(parentDescriptor.getTags())); return allTags; } @Override public List> getEnclosingTestClasses() { TestDescriptor parent = getParent().orElse(null); if (parent instanceof ClassBasedTestDescriptor) { ClassBasedTestDescriptor parentClassDescriptor = (ClassBasedTestDescriptor) parent; List> result = new ArrayList<>(parentClassDescriptor.getEnclosingTestClasses()); result.add(parentClassDescriptor.getTestClass()); return result; } return emptyList(); } // --- Node ---------------------------------------------------------------- @Override protected TestInstances instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext, ExtensionRegistry registry, ExtensionRegistrar registrar, ExtensionContext extensionContext, ThrowableCollector throwableCollector) { // Extensions registered for nested classes and below are not to be used for instantiating and initializing outer classes ExtensionRegistry extensionRegistryForOuterInstanceCreation = parentExecutionContext.getExtensionRegistry(); TestInstances outerInstances = parentExecutionContext.getTestInstancesProvider().getTestInstances( extensionRegistryForOuterInstanceCreation, registrar, throwableCollector); return instantiateTestClass(Optional.of(outerInstances), registry, extensionContext); } } TestFactoryTestDescriptor.java000066400000000000000000000175711455764576500367310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.MethodSourceSupport.METHOD_SCHEME; import static org.junit.platform.engine.support.descriptor.ClassSource.CLASS_SCHEME; import static org.junit.platform.engine.support.descriptor.ClasspathResourceSource.CLASSPATH_SCHEME; import java.lang.reflect.Method; import java.net.URI; import java.util.Iterator; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.ClasspathResourceSource; import org.junit.platform.engine.support.descriptor.UriSource; /** * {@link org.junit.platform.engine.TestDescriptor TestDescriptor} for * {@link org.junit.jupiter.api.TestFactory @TestFactory} methods. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class TestFactoryTestDescriptor extends TestMethodTestDescriptor implements Filterable { public static final String SEGMENT_TYPE = "test-factory"; public static final String DYNAMIC_CONTAINER_SEGMENT_TYPE = "dynamic-container"; public static final String DYNAMIC_TEST_SEGMENT_TYPE = "dynamic-test"; private static final ReflectiveInterceptorCall interceptorCall = InvocationInterceptor::interceptTestFactoryMethod; private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); private final DynamicDescendantFilter dynamicDescendantFilter = new DynamicDescendantFilter(); public TestFactoryTestDescriptor(UniqueId uniqueId, Class testClass, Method testMethod, JupiterConfiguration configuration) { super(uniqueId, testClass, testMethod, configuration); } // --- Filterable ---------------------------------------------------------- @Override public DynamicDescendantFilter getDynamicDescendantFilter() { return dynamicDescendantFilter; } // --- TestDescriptor ------------------------------------------------------ @Override public Type getType() { return Type.CONTAINER; } @Override public boolean mayRegisterTests() { return true; } // --- Node ---------------------------------------------------------------- @Override protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { ExtensionContext extensionContext = context.getExtensionContext(); context.getThrowableCollector().execute(() -> { Object instance = extensionContext.getRequiredTestInstance(); Object testFactoryMethodResult = executableInvoker.invoke(getTestMethod(), instance, extensionContext, context.getExtensionRegistry(), interceptorCall); TestSource defaultTestSource = getSource().orElseThrow( () -> new JUnitException("Illegal state: TestSource must be present")); try (Stream dynamicNodeStream = toDynamicNodeStream(testFactoryMethodResult)) { int index = 1; Iterator iterator = dynamicNodeStream.iterator(); while (iterator.hasNext()) { DynamicNode dynamicNode = iterator.next(); Optional descriptor = createDynamicDescriptor(this, dynamicNode, index, defaultTestSource, getDynamicDescendantFilter(), configuration); descriptor.ifPresent(dynamicTestExecutor::execute); index++; } } catch (ClassCastException ex) { throw invalidReturnTypeException(ex); } dynamicTestExecutor.awaitFinished(); }); } @SuppressWarnings("unchecked") private Stream toDynamicNodeStream(Object testFactoryMethodResult) { if (testFactoryMethodResult instanceof DynamicNode) { return Stream.of((DynamicNode) testFactoryMethodResult); } try { return (Stream) CollectionUtils.toStream(testFactoryMethodResult); } catch (PreconditionViolationException ex) { throw invalidReturnTypeException(ex); } } private JUnitException invalidReturnTypeException(Throwable cause) { String message = String.format( "@TestFactory method [%s] must return a single %2$s or a Stream, Collection, Iterable, Iterator, or array of %2$s.", getTestMethod().toGenericString(), DynamicNode.class.getName()); return new JUnitException(message, cause); } static Optional createDynamicDescriptor(JupiterTestDescriptor parent, DynamicNode node, int index, TestSource defaultTestSource, DynamicDescendantFilter dynamicDescendantFilter, JupiterConfiguration configuration) { UniqueId uniqueId; Supplier descriptorCreator; Optional customTestSource = node.getTestSourceUri().map(TestFactoryTestDescriptor::fromUri); TestSource source = customTestSource.orElse(defaultTestSource); if (node instanceof DynamicTest) { DynamicTest test = (DynamicTest) node; uniqueId = parent.getUniqueId().append(DYNAMIC_TEST_SEGMENT_TYPE, "#" + index); descriptorCreator = () -> new DynamicTestTestDescriptor(uniqueId, index, test, source, configuration); } else { DynamicContainer container = (DynamicContainer) node; uniqueId = parent.getUniqueId().append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#" + index); descriptorCreator = () -> new DynamicContainerTestDescriptor(uniqueId, index, container, source, dynamicDescendantFilter.withoutIndexFiltering(), configuration); } if (dynamicDescendantFilter.test(uniqueId, index - 1)) { JupiterTestDescriptor descriptor = descriptorCreator.get(); descriptor.setParent(parent); return Optional.of(descriptor); } return Optional.empty(); } /** * @since 5.3 */ static TestSource fromUri(URI uri) { Preconditions.notNull(uri, "URI must not be null"); if (CLASSPATH_SCHEME.equals(uri.getScheme())) { return ClasspathResourceSource.from(uri); } if (CLASS_SCHEME.equals(uri.getScheme())) { return ClassSource.from(uri); } if (METHOD_SCHEME.equals(uri.getScheme())) { return MethodSourceSupport.from(uri); } return UriSource.from(uri); } /** * Override {@link TestMethodTestDescriptor#nodeSkipped} as a no-op, since * the {@code TestWatcher} API is not supported for {@code @TestFactory} * containers. * * @since 5.4 */ @Override public void nodeSkipped(JupiterEngineExecutionContext context, TestDescriptor descriptor, SkipResult result) { /* no-op */ } /** * Override {@link TestMethodTestDescriptor#nodeFinished} as a no-op, since * the {@code TestWatcher} API is not supported for {@code @TestFactory} * containers. * * @since 5.4 */ @Override public void nodeFinished(JupiterEngineExecutionContext context, TestDescriptor descriptor, TestExecutionResult result) { /* no-op */ } } TestInstanceLifecycleUtils.java000066400000000000000000000026241455764576500370210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; /** * Collection of utilities for retrieving the test instance lifecycle mode. * * @since 5.0 * @see TestInstance * @see TestInstance.Lifecycle */ @API(status = INTERNAL, since = "5.0") public final class TestInstanceLifecycleUtils { private TestInstanceLifecycleUtils() { /* no-op */ } static TestInstance.Lifecycle getTestInstanceLifecycle(Class testClass, JupiterConfiguration configuration) { Preconditions.notNull(testClass, "testClass must not be null"); Preconditions.notNull(configuration, "configuration must not be null"); // @formatter:off return AnnotationUtils.findAnnotation(testClass, TestInstance.class) .map(TestInstance::value) .orElseGet(configuration::getDefaultTestInstanceLifecycle); // @formatter:on } } TestMethodTestDescriptor.java000066400000000000000000000322511455764576500365320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromExecutableParameters; import static org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory.createThrowableCollector; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.lang.reflect.Method; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.LifecycleMethodExecutionExceptionHandler; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestWatcher; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.AfterEachMethodAdapter; import org.junit.jupiter.engine.execution.BeforeEachMethodAdapter; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * {@link TestDescriptor} for {@link org.junit.jupiter.api.Test @Test} methods. * *

Default Display Names

* *

The default display name for a test method is the name of the method * concatenated with a comma-separated list of parameter types in parentheses. * The names of parameter types are retrieved using {@link Class#getSimpleName()}. * For example, the default display name for the following test method is * {@code testUser(TestInfo, User)}. * *

 *   {@literal @}Test
 *   void testUser(TestInfo testInfo, {@literal @}Mock User user) { ... }
 * 
* * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class TestMethodTestDescriptor extends MethodBasedTestDescriptor { public static final String SEGMENT_TYPE = "method"; private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); private static final ReflectiveInterceptorCall defaultInterceptorCall = ReflectiveInterceptorCall.ofVoidMethod( InvocationInterceptor::interceptTestMethod); private final ReflectiveInterceptorCall interceptorCall; public TestMethodTestDescriptor(UniqueId uniqueId, Class testClass, Method testMethod, JupiterConfiguration configuration) { super(uniqueId, testClass, testMethod, configuration); this.interceptorCall = defaultInterceptorCall; } TestMethodTestDescriptor(UniqueId uniqueId, String displayName, Class testClass, Method testMethod, JupiterConfiguration configuration, ReflectiveInterceptorCall interceptorCall) { super(uniqueId, displayName, testClass, testMethod, configuration); this.interceptorCall = interceptorCall; } @Override public Type getType() { return Type.TEST; } // --- Node ---------------------------------------------------------------- @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = populateNewExtensionRegistry(context); ThrowableCollector throwableCollector = createThrowableCollector(); ExecutableInvoker executableInvoker = new DefaultExecutableInvoker(context); MethodExtensionContext extensionContext = new MethodExtensionContext(context.getExtensionContext(), context.getExecutionListener(), this, context.getConfiguration(), throwableCollector, executableInvoker); throwableCollector.execute(() -> { TestInstances testInstances = context.getTestInstancesProvider().getTestInstances(registry, throwableCollector); extensionContext.setTestInstances(testInstances); }); // @formatter:off return context.extend() .withExtensionRegistry(registry) .withExtensionContext(extensionContext) .withThrowableCollector(throwableCollector) .build(); // @formatter:on } protected MutableExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation( context.getExtensionRegistry(), getTestMethod()); registerExtensionsFromExecutableParameters(registry, getTestMethod()); return registry; } @Override public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { ThrowableCollector throwableCollector = context.getThrowableCollector(); // @formatter:off invokeBeforeEachCallbacks(context); if (throwableCollector.isEmpty()) { invokeBeforeEachMethods(context); if (throwableCollector.isEmpty()) { invokeBeforeTestExecutionCallbacks(context); if (throwableCollector.isEmpty()) { invokeTestMethod(context, dynamicTestExecutor); } invokeAfterTestExecutionCallbacks(context); } invokeAfterEachMethods(context); } invokeAfterEachCallbacks(context); // @formatter:on return context; } @Override public void cleanUp(JupiterEngineExecutionContext context) throws Exception { if (isPerMethodLifecycle(context) && context.getExtensionContext().getTestInstance().isPresent()) { invokeTestInstancePreDestroyCallbacks(context); } context.getThrowableCollector().execute(() -> super.cleanUp(context)); context.getThrowableCollector().assertEmpty(); } private boolean isPerMethodLifecycle(JupiterEngineExecutionContext context) { return context.getExtensionContext().getTestInstanceLifecycle().orElse( Lifecycle.PER_CLASS) == Lifecycle.PER_METHOD; } private void invokeBeforeEachCallbacks(JupiterEngineExecutionContext context) { invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(BeforeEachCallback.class, context, (callback, extensionContext) -> callback.beforeEach(extensionContext)); } private void invokeBeforeEachMethods(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(BeforeEachMethodAdapter.class, context, (adapter, extensionContext) -> { try { adapter.invokeBeforeEachMethod(extensionContext, registry); } catch (Throwable throwable) { invokeBeforeEachExecutionExceptionHandlers(extensionContext, registry, throwable); } }); } private void invokeBeforeEachExecutionExceptionHandlers(ExtensionContext context, ExtensionRegistry registry, Throwable throwable) { invokeExecutionExceptionHandlers(LifecycleMethodExecutionExceptionHandler.class, registry, throwable, (handler, handledThrowable) -> handler.handleBeforeEachMethodExecutionException(context, handledThrowable)); } private void invokeBeforeTestExecutionCallbacks(JupiterEngineExecutionContext context) { invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(BeforeTestExecutionCallback.class, context, (callback, extensionContext) -> callback.beforeTestExecution(extensionContext)); } private void invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(Class type, JupiterEngineExecutionContext context, CallbackInvoker callbackInvoker) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); for (T callback : registry.getExtensions(type)) { throwableCollector.execute(() -> callbackInvoker.invoke(callback, extensionContext)); if (throwableCollector.isNotEmpty()) { break; } } } protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); throwableCollector.execute(() -> { try { Method testMethod = getTestMethod(); Object instance = extensionContext.getRequiredTestInstance(); executableInvoker.invoke(testMethod, instance, extensionContext, context.getExtensionRegistry(), interceptorCall); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); invokeTestExecutionExceptionHandlers(context.getExtensionRegistry(), extensionContext, throwable); } }); } private void invokeTestExecutionExceptionHandlers(ExtensionRegistry registry, ExtensionContext context, Throwable throwable) { invokeExecutionExceptionHandlers(TestExecutionExceptionHandler.class, registry, throwable, (handler, handledThrowable) -> handler.handleTestExecutionException(context, handledThrowable)); } private void invokeAfterTestExecutionCallbacks(JupiterEngineExecutionContext context) { invokeAllAfterMethodsOrCallbacks(AfterTestExecutionCallback.class, context, (callback, extensionContext) -> callback.afterTestExecution(extensionContext)); } private void invokeAfterEachMethods(JupiterEngineExecutionContext context) { ExtensionRegistry registry = context.getExtensionRegistry(); invokeAllAfterMethodsOrCallbacks(AfterEachMethodAdapter.class, context, (adapter, extensionContext) -> { try { adapter.invokeAfterEachMethod(extensionContext, registry); } catch (Throwable throwable) { invokeAfterEachExecutionExceptionHandlers(extensionContext, registry, throwable); } }); } private void invokeAfterEachExecutionExceptionHandlers(ExtensionContext context, ExtensionRegistry registry, Throwable throwable) { invokeExecutionExceptionHandlers(LifecycleMethodExecutionExceptionHandler.class, registry, throwable, (handler, handledThrowable) -> handler.handleAfterEachMethodExecutionException(context, handledThrowable)); } private void invokeAfterEachCallbacks(JupiterEngineExecutionContext context) { invokeAllAfterMethodsOrCallbacks(AfterEachCallback.class, context, (callback, extensionContext) -> callback.afterEach(extensionContext)); } private void invokeTestInstancePreDestroyCallbacks(JupiterEngineExecutionContext context) { invokeAllAfterMethodsOrCallbacks(TestInstancePreDestroyCallback.class, context, TestInstancePreDestroyCallback::preDestroyTestInstance); } private void invokeAllAfterMethodsOrCallbacks(Class type, JupiterEngineExecutionContext context, CallbackInvoker callbackInvoker) { ExtensionRegistry registry = context.getExtensionRegistry(); ExtensionContext extensionContext = context.getExtensionContext(); ThrowableCollector throwableCollector = context.getThrowableCollector(); forEachInReverseOrder(registry.getExtensions(type), callback -> { throwableCollector.execute(() -> callbackInvoker.invoke(callback, extensionContext)); }); } /** * Invoke {@link TestWatcher#testSuccessful testSuccessful()}, * {@link TestWatcher#testAborted testAborted()}, or * {@link TestWatcher#testFailed testFailed()} on each * registered {@link TestWatcher} according to the status of the supplied * {@link TestExecutionResult}, in reverse registration order. * * @since 5.4 */ @Override public void nodeFinished(JupiterEngineExecutionContext context, TestDescriptor descriptor, TestExecutionResult result) { if (context != null) { ExtensionContext extensionContext = context.getExtensionContext(); TestExecutionResult.Status status = result.getStatus(); invokeTestWatchers(context, true, watcher -> { switch (status) { case SUCCESSFUL: watcher.testSuccessful(extensionContext); break; case ABORTED: watcher.testAborted(extensionContext, result.getThrowable().orElse(null)); break; case FAILED: watcher.testFailed(extensionContext, result.getThrowable().orElse(null)); break; } }); } } /** * @since 5.5 */ @FunctionalInterface private interface CallbackInvoker { void invoke(T t, ExtensionContext context) throws Throwable; } } TestTemplateExtensionContext.java000066400000000000000000000045441455764576500374340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.Node; /** * @since 5.0 */ final class TestTemplateExtensionContext extends AbstractExtensionContext { private final TestInstances testInstances; TestTemplateExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, TestTemplateTestDescriptor testDescriptor, JupiterConfiguration configuration, TestInstances testInstances, ExecutableInvoker executableInvoker) { super(parent, engineExecutionListener, testDescriptor, configuration, executableInvoker); this.testInstances = testInstances; } @Override public Optional getElement() { return Optional.of(getTestDescriptor().getTestMethod()); } @Override public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } @Override public Optional getTestInstanceLifecycle() { return getParent().flatMap(ExtensionContext::getTestInstanceLifecycle); } @Override public Optional getTestInstance() { return getTestInstances().map(TestInstances::getInnermostInstance); } @Override public Optional getTestInstances() { return Optional.ofNullable(this.testInstances); } @Override public Optional getTestMethod() { return Optional.of(getTestDescriptor().getTestMethod()); } @Override public Optional getExecutionException() { return Optional.empty(); } @Override protected Node.ExecutionMode getPlatformExecutionMode() { return getTestDescriptor().getExecutionMode(); } } TestTemplateInvocationTestDescriptor.java000066400000000000000000000056121455764576500411200ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.Collections.emptySet; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Method; import java.util.Set; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; /** * {@link TestDescriptor} for a {@link org.junit.jupiter.api.TestTemplate @TestTemplate} * invocation. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class TestTemplateInvocationTestDescriptor extends TestMethodTestDescriptor { public static final String SEGMENT_TYPE = "test-template-invocation"; private static final ReflectiveInterceptorCall interceptorCall = ReflectiveInterceptorCall.ofVoidMethod( InvocationInterceptor::interceptTestTemplateMethod); private TestTemplateInvocationContext invocationContext; private final int index; TestTemplateInvocationTestDescriptor(UniqueId uniqueId, Class testClass, Method templateMethod, TestTemplateInvocationContext invocationContext, int index, JupiterConfiguration configuration) { super(uniqueId, invocationContext.getDisplayName(index), testClass, templateMethod, configuration, interceptorCall); this.invocationContext = invocationContext; this.index = index; } @Override public Set getExclusiveResources() { // @ResourceLock annotations are already collected and returned by the enclosing container return emptySet(); } @Override public String getLegacyReportingName() { return super.getLegacyReportingName() + "[" + index + "]"; } @Override protected MutableExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = super.populateNewExtensionRegistry(context); invocationContext.getAdditionalExtensions().forEach( extension -> registry.registerExtension(extension, invocationContext)); return registry; } @Override public void after(JupiterEngineExecutionContext context) { // forget invocationContext so it can be garbage collected invocationContext = null; } } TestTemplateTestDescriptor.java000066400000000000000000000142171455764576500370670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation; import java.lang.reflect.Method; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; /** * {@link TestDescriptor} for {@link org.junit.jupiter.api.TestTemplate @TestTemplate} * methods. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class TestTemplateTestDescriptor extends MethodBasedTestDescriptor implements Filterable { public static final String SEGMENT_TYPE = "test-template"; private final DynamicDescendantFilter dynamicDescendantFilter = new DynamicDescendantFilter(); public TestTemplateTestDescriptor(UniqueId uniqueId, Class testClass, Method templateMethod, JupiterConfiguration configuration) { super(uniqueId, testClass, templateMethod, configuration); } // --- Filterable ---------------------------------------------------------- @Override public DynamicDescendantFilter getDynamicDescendantFilter() { return dynamicDescendantFilter; } // --- TestDescriptor ------------------------------------------------------ @Override public Type getType() { return Type.CONTAINER; } @Override public boolean mayRegisterTests() { return true; } // --- Node ---------------------------------------------------------------- @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception { MutableExtensionRegistry registry = populateNewExtensionRegistryFromExtendWithAnnotation( context.getExtensionRegistry(), getTestMethod()); // The test instance should be properly maintained by the enclosing class's ExtensionContext. TestInstances testInstances = context.getExtensionContext().getTestInstances().orElse(null); ExecutableInvoker executableInvoker = new DefaultExecutableInvoker(context); ExtensionContext extensionContext = new TestTemplateExtensionContext(context.getExtensionContext(), context.getExecutionListener(), this, context.getConfiguration(), testInstances, executableInvoker); // @formatter:off return context.extend() .withExtensionRegistry(registry) .withExtensionContext(extensionContext) .build(); // @formatter:on } @Override public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) throws Exception { ExtensionContext extensionContext = context.getExtensionContext(); List providers = validateProviders(extensionContext, context.getExtensionRegistry()); AtomicInteger invocationIndex = new AtomicInteger(); // @formatter:off providers.stream() .flatMap(provider -> provider.provideTestTemplateInvocationContexts(extensionContext)) .map(invocationContext -> createInvocationTestDescriptor(invocationContext, invocationIndex.incrementAndGet())) .filter(Optional::isPresent) .map(Optional::get) .forEach(invocationTestDescriptor -> execute(dynamicTestExecutor, invocationTestDescriptor)); // @formatter:on validateWasAtLeastInvokedOnce(invocationIndex.get(), providers); return context; } private List validateProviders(ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { // @formatter:off List providers = extensionRegistry.stream(TestTemplateInvocationContextProvider.class) .filter(provider -> provider.supportsTestTemplate(extensionContext)) .collect(toList()); // @formatter:on return Preconditions.notEmpty(providers, () -> String.format("You must register at least one %s that supports @TestTemplate method [%s]", TestTemplateInvocationContextProvider.class.getSimpleName(), getTestMethod())); } private Optional createInvocationTestDescriptor(TestTemplateInvocationContext invocationContext, int index) { UniqueId uniqueId = getUniqueId().append(TestTemplateInvocationTestDescriptor.SEGMENT_TYPE, "#" + index); if (getDynamicDescendantFilter().test(uniqueId, index - 1)) { return Optional.of(new TestTemplateInvocationTestDescriptor(uniqueId, getTestClass(), getTestMethod(), invocationContext, index, configuration)); } return Optional.empty(); } private void execute(DynamicTestExecutor dynamicTestExecutor, TestDescriptor testDescriptor) { testDescriptor.setParent(this); dynamicTestExecutor.execute(testDescriptor); } private void validateWasAtLeastInvokedOnce(int invocationIndex, List providers) { Preconditions.condition(invocationIndex > 0, () -> "None of the supporting " + TestTemplateInvocationContextProvider.class.getSimpleName() + "s " + providers.stream().map(provider -> provider.getClass().getSimpleName()).collect( joining(", ", "[", "]")) + " provided a non-empty stream"); } } package-info.java000066400000000000000000000001651455764576500340760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/** * Test descriptors used within the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.descriptor; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/000077500000000000000000000000001455764576500306155ustar00rootroot00000000000000AbstractAnnotatedDescriptorWrapper.java000066400000000000000000000040551455764576500404060ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.util.List; import java.util.Optional; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; /** * Abstract base class for wrappers for test descriptors based on annotated * elements. * * @since 5.8 */ abstract class AbstractAnnotatedDescriptorWrapper { private final TestDescriptor testDescriptor; private final E annotatedElement; AbstractAnnotatedDescriptorWrapper(TestDescriptor testDescriptor, E annotatedElement) { this.testDescriptor = testDescriptor; this.annotatedElement = annotatedElement; } E getAnnotatedElement() { return this.annotatedElement; } TestDescriptor getTestDescriptor() { return this.testDescriptor; } public final String getDisplayName() { return this.testDescriptor.getDisplayName(); } public final boolean isAnnotated(Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); return AnnotationUtils.isAnnotated(getAnnotatedElement(), annotationType); } public final Optional findAnnotation(Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); return AnnotationUtils.findAnnotation(getAnnotatedElement(), annotationType); } public final List findRepeatableAnnotations(Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); return AnnotationUtils.findRepeatableAnnotations(getAnnotatedElement(), annotationType); } } AbstractOrderingVisitor.java000066400000000000000000000163261455764576500362260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static java.util.stream.Collectors.toCollection; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestDescriptor; /** * Abstract base class for {@linkplain TestDescriptor.Visitor visitors} that * order children nodes. * * @param the parent container type to search in for matching children * @param the type of children (containers or tests) to order * @param the wrapper type for the children to order * @since 5.8 */ abstract class AbstractOrderingVisitor> implements TestDescriptor.Visitor { private static final Logger logger = LoggerFactory.getLogger(AbstractOrderingVisitor.class); @SuppressWarnings("unchecked") protected void doWithMatchingDescriptor(Class parentTestDescriptorType, TestDescriptor testDescriptor, Consumer action, Function errorMessageBuilder) { if (parentTestDescriptorType.isInstance(testDescriptor)) { PARENT parentTestDescriptor = (PARENT) testDescriptor; try { action.accept(parentTestDescriptor); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); logger.error(t, () -> errorMessageBuilder.apply(parentTestDescriptor)); } } } protected void orderChildrenTestDescriptors(TestDescriptor parentTestDescriptor, Class matchingChildrenType, Function descriptorWrapperFactory, DescriptorWrapperOrderer descriptorWrapperOrderer) { Set children = parentTestDescriptor.getChildren(); List matchingDescriptorWrappers = children.stream()// .filter(matchingChildrenType::isInstance)// .map(matchingChildrenType::cast)// .map(descriptorWrapperFactory)// .collect(toCollection(ArrayList::new)); // If there are no children to order, abort early. if (matchingDescriptorWrappers.isEmpty()) { return; } if (descriptorWrapperOrderer.canOrderWrappers()) { List nonMatchingTestDescriptors = children.stream()// .filter(childTestDescriptor -> !matchingChildrenType.isInstance(childTestDescriptor))// .collect(Collectors.toList()); // Make a local copy for later validation Set originalWrappers = new LinkedHashSet<>(matchingDescriptorWrappers); descriptorWrapperOrderer.orderWrappers(matchingDescriptorWrappers); int difference = matchingDescriptorWrappers.size() - originalWrappers.size(); if (difference > 0) { descriptorWrapperOrderer.logDescriptorsAddedWarning(difference); } else if (difference < 0) { descriptorWrapperOrderer.logDescriptorsRemovedWarning(difference); } Set orderedTestDescriptors = matchingDescriptorWrappers.stream()// .filter(originalWrappers::contains)// .map(AbstractAnnotatedDescriptorWrapper::getTestDescriptor)// .collect(toCollection(LinkedHashSet::new)); // There is currently no way to removeAll or addAll children at once, so we // first remove them all and then add them all back. Stream.concat(orderedTestDescriptors.stream(), nonMatchingTestDescriptors.stream())// .forEach(parentTestDescriptor::removeChild); // If we are ordering children of type ClassBasedTestDescriptor, that means we // are ordering top-level classes or @Nested test classes. Thus, the // nonMatchingTestDescriptors list is either empty (for top-level classes) or // contains only local test methods (for @Nested classes) which must be executed // before tests in @Nested test classes. So we add the test methods before adding // the @Nested test classes. if (matchingChildrenType == ClassBasedTestDescriptor.class) { Stream.concat(nonMatchingTestDescriptors.stream(), orderedTestDescriptors.stream())// .forEach(parentTestDescriptor::addChild); } // Otherwise, we add the ordered descriptors before the non-matching descriptors, // which is the case when we are ordering test methods. In other words, local // test methods always get added before @Nested test classes. else { Stream.concat(orderedTestDescriptors.stream(), nonMatchingTestDescriptors.stream())// .forEach(parentTestDescriptor::addChild); } } // Recurse through the children in order to support ordering for @Nested test classes. matchingDescriptorWrappers.forEach(descriptorWrapper -> { TestDescriptor newParentTestDescriptor = descriptorWrapper.getTestDescriptor(); DescriptorWrapperOrderer newDescriptorWrapperOrderer = getDescriptorWrapperOrderer(descriptorWrapperOrderer, descriptorWrapper); orderChildrenTestDescriptors(newParentTestDescriptor, matchingChildrenType, descriptorWrapperFactory, newDescriptorWrapperOrderer); }); } /** * Get the {@link DescriptorWrapperOrderer} for the supplied {@link AbstractAnnotatedDescriptorWrapper}. * *

The default implementation returns the supplied {@code DescriptorWrapperOrderer}. * * @return a new {@code DescriptorWrapperOrderer} or the one supplied as an argument */ protected DescriptorWrapperOrderer getDescriptorWrapperOrderer( DescriptorWrapperOrderer inheritedDescriptorWrapperOrderer, AbstractAnnotatedDescriptorWrapper descriptorWrapper) { return inheritedDescriptorWrapperOrderer; } protected class DescriptorWrapperOrderer { private final Consumer> orderingAction; private final MessageGenerator descriptorsAddedMessageGenerator; private final MessageGenerator descriptorsRemovedMessageGenerator; DescriptorWrapperOrderer(Consumer> orderingAction, MessageGenerator descriptorsAddedMessageGenerator, MessageGenerator descriptorsRemovedMessageGenerator) { this.orderingAction = orderingAction; this.descriptorsAddedMessageGenerator = descriptorsAddedMessageGenerator; this.descriptorsRemovedMessageGenerator = descriptorsRemovedMessageGenerator; } private boolean canOrderWrappers() { return this.orderingAction != null; } private void orderWrappers(List wrappers) { this.orderingAction.accept(wrappers); } private void logDescriptorsAddedWarning(int number) { logger.warn(() -> this.descriptorsAddedMessageGenerator.generateMessage(number)); } private void logDescriptorsRemovedWarning(int number) { logger.warn(() -> this.descriptorsRemovedMessageGenerator.generateMessage(Math.abs(number))); } } @FunctionalInterface protected interface MessageGenerator { String generateMessage(int number); } } ClassOrderingVisitor.java000066400000000000000000000066171455764576500355320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.lang.reflect.AnnotatedElement; import java.util.List; import java.util.function.Consumer; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.TestClassOrder; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; /** * @since 5.8 */ class ClassOrderingVisitor extends AbstractOrderingVisitor { private final JupiterConfiguration configuration; ClassOrderingVisitor(JupiterConfiguration configuration) { this.configuration = configuration; } @Override public void visit(TestDescriptor testDescriptor) { ClassOrderer globalClassOrderer = this.configuration.getDefaultTestClassOrderer().orElse(null); doWithMatchingDescriptor(JupiterEngineDescriptor.class, testDescriptor, descriptor -> orderContainedClasses(descriptor, globalClassOrderer), descriptor -> "Failed to order classes"); } private void orderContainedClasses(JupiterEngineDescriptor jupiterEngineDescriptor, ClassOrderer classOrderer) { orderChildrenTestDescriptors(// jupiterEngineDescriptor, // ClassBasedTestDescriptor.class, // DefaultClassDescriptor::new, // createDescriptorWrapperOrderer(classOrderer)); } @Override protected DescriptorWrapperOrderer getDescriptorWrapperOrderer( DescriptorWrapperOrderer inheritedDescriptorWrapperOrderer, AbstractAnnotatedDescriptorWrapper descriptorWrapper) { AnnotatedElement annotatedElement = descriptorWrapper.getAnnotatedElement(); return AnnotationUtils.findAnnotation(annotatedElement, TestClassOrder.class)// .map(TestClassOrder::value)// . map(ReflectionUtils::newInstance)// .map(this::createDescriptorWrapperOrderer)// .orElse(inheritedDescriptorWrapperOrderer); } private DescriptorWrapperOrderer createDescriptorWrapperOrderer(ClassOrderer classOrderer) { Consumer> orderingAction = classOrderer == null ? null : // classDescriptors -> classOrderer.orderClasses( new DefaultClassOrdererContext(classDescriptors, this.configuration)); MessageGenerator descriptorsAddedMessageGenerator = number -> String.format( "ClassOrderer [%s] added %s ClassDescriptor(s) which will be ignored.", nullSafeToString(classOrderer), number); MessageGenerator descriptorsRemovedMessageGenerator = number -> String.format( "ClassOrderer [%s] removed %s ClassDescriptor(s) which will be retained with arbitrary ordering.", nullSafeToString(classOrderer), number); return new DescriptorWrapperOrderer(orderingAction, descriptorsAddedMessageGenerator, descriptorsRemovedMessageGenerator); } private static String nullSafeToString(ClassOrderer classOrderer) { return (classOrderer != null ? classOrderer.getClass().getName() : ""); } } ClassSelectorResolver.java000066400000000000000000000157311455764576500357000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toCollection; import static org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.isTestOrTestFactoryOrTestTemplateMethod; import static org.junit.platform.commons.support.ReflectionSupport.streamNestedClasses; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Stream; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor; import org.junit.jupiter.engine.discovery.predicates.IsNestedTestClass; import org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.NestedClassSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.discovery.SelectorResolver; /** * @since 5.5 */ class ClassSelectorResolver implements SelectorResolver { private static final IsTestClassWithTests isTestClassWithTests = new IsTestClassWithTests(); private static final IsNestedTestClass isNestedTestClass = new IsNestedTestClass(); private final Predicate classNameFilter; private final JupiterConfiguration configuration; ClassSelectorResolver(Predicate classNameFilter, JupiterConfiguration configuration) { this.classNameFilter = classNameFilter; this.configuration = configuration; } @Override public Resolution resolve(ClassSelector selector, Context context) { Class testClass = selector.getJavaClass(); if (isTestClassWithTests.test(testClass)) { // Nested tests are never filtered out if (classNameFilter.test(testClass.getName())) { return toResolution( context.addToParent(parent -> Optional.of(newClassTestDescriptor(parent, testClass)))); } } else if (isNestedTestClass.test(testClass)) { return toResolution(context.addToParent(() -> DiscoverySelectors.selectClass(testClass.getEnclosingClass()), parent -> Optional.of(newNestedClassTestDescriptor(parent, testClass)))); } return unresolved(); } @Override public Resolution resolve(NestedClassSelector selector, Context context) { if (isNestedTestClass.test(selector.getNestedClass())) { return toResolution(context.addToParent(() -> selectClass(selector.getEnclosingClasses()), parent -> Optional.of(newNestedClassTestDescriptor(parent, selector.getNestedClass())))); } return unresolved(); } @Override public Resolution resolve(UniqueIdSelector selector, Context context) { UniqueId uniqueId = selector.getUniqueId(); UniqueId.Segment lastSegment = uniqueId.getLastSegment(); if (ClassTestDescriptor.SEGMENT_TYPE.equals(lastSegment.getType())) { String className = lastSegment.getValue(); return ReflectionUtils.tryToLoadClass(className).toOptional().filter(isTestClassWithTests).map( testClass -> toResolution( context.addToParent(parent -> Optional.of(newClassTestDescriptor(parent, testClass))))).orElse( unresolved()); } if (NestedClassTestDescriptor.SEGMENT_TYPE.equals(lastSegment.getType())) { String simpleClassName = lastSegment.getValue(); return toResolution(context.addToParent(() -> selectUniqueId(uniqueId.removeLastSegment()), parent -> { if (parent instanceof ClassBasedTestDescriptor) { Class parentTestClass = ((ClassBasedTestDescriptor) parent).getTestClass(); return ReflectionUtils.findNestedClasses(parentTestClass, isNestedTestClass.and( where(Class::getSimpleName, isEqual(simpleClassName)))).stream().findFirst().flatMap( testClass -> Optional.of(newNestedClassTestDescriptor(parent, testClass))); } return Optional.empty(); })); } return unresolved(); } private ClassTestDescriptor newClassTestDescriptor(TestDescriptor parent, Class testClass) { return new ClassTestDescriptor( parent.getUniqueId().append(ClassTestDescriptor.SEGMENT_TYPE, testClass.getName()), testClass, configuration); } private NestedClassTestDescriptor newNestedClassTestDescriptor(TestDescriptor parent, Class testClass) { return new NestedClassTestDescriptor( parent.getUniqueId().append(NestedClassTestDescriptor.SEGMENT_TYPE, testClass.getSimpleName()), testClass, configuration); } private Resolution toResolution(Optional testDescriptor) { return testDescriptor.map(it -> { Class testClass = it.getTestClass(); List> testClasses = new ArrayList<>(it.getEnclosingTestClasses()); testClasses.add(testClass); // @formatter:off return Resolution.match(Match.exact(it, () -> { Stream methods = findMethods(testClass, isTestOrTestFactoryOrTestTemplateMethod).stream() .map(method -> selectMethod(testClasses, method)); Stream nestedClasses = streamNestedClasses(testClass, isNestedTestClass) .map(nestedClass -> DiscoverySelectors.selectNestedClass(testClasses, nestedClass)); return Stream.concat(methods, nestedClasses).collect(toCollection((Supplier>) LinkedHashSet::new)); })); // @formatter:on }).orElse(unresolved()); } private DiscoverySelector selectClass(List> classes) { if (classes.size() == 1) { return DiscoverySelectors.selectClass(classes.get(0)); } int lastIndex = classes.size() - 1; return DiscoverySelectors.selectNestedClass(classes.subList(0, lastIndex), classes.get(lastIndex)); } private DiscoverySelector selectMethod(List> classes, Method method) { if (classes.size() == 1) { return DiscoverySelectors.selectMethod(classes.get(0), method); } int lastIndex = classes.size() - 1; return DiscoverySelectors.selectNestedMethod(classes.subList(0, lastIndex), classes.get(lastIndex), method); } } DefaultClassDescriptor.java000066400000000000000000000021501455764576500360100ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import org.junit.jupiter.api.ClassDescriptor; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of {@link ClassDescriptor}, backed by * a {@link ClassBasedTestDescriptor}. * * @since 5.8 */ class DefaultClassDescriptor extends AbstractAnnotatedDescriptorWrapper> implements ClassDescriptor { DefaultClassDescriptor(ClassBasedTestDescriptor testDescriptor) { super(testDescriptor, testDescriptor.getTestClass()); } @Override public final Class getTestClass() { return getAnnotatedElement(); } @Override public String toString() { return new ToStringBuilder(this).append("class", getTestClass().toGenericString()).toString(); } } DefaultClassOrdererContext.java000066400000000000000000000024161455764576500366460ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.ClassDescriptor; import org.junit.jupiter.api.ClassOrdererContext; import org.junit.jupiter.engine.config.JupiterConfiguration; /** * Default implementation of {@link ClassOrdererContext}. * * @since 5.8 */ class DefaultClassOrdererContext implements ClassOrdererContext { private final List classDescriptors; private final JupiterConfiguration configuration; DefaultClassOrdererContext(List classDescriptors, JupiterConfiguration configuration) { this.classDescriptors = classDescriptors; this.configuration = configuration; } @Override public List getClassDescriptors() { return this.classDescriptors; } @Override public Optional getConfigurationParameter(String key) { return this.configuration.getRawConfigurationParameter(key); } } DefaultMethodDescriptor.java000066400000000000000000000022121455764576500361620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.lang.reflect.Method; import org.junit.jupiter.api.MethodDescriptor; import org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of {@link MethodDescriptor}, backed by * a {@link MethodBasedTestDescriptor}. * * @since 5.4 */ class DefaultMethodDescriptor extends AbstractAnnotatedDescriptorWrapper implements MethodDescriptor { DefaultMethodDescriptor(MethodBasedTestDescriptor testDescriptor) { super(testDescriptor, testDescriptor.getTestMethod()); } @Override public final Method getMethod() { return getAnnotatedElement(); } @Override public String toString() { return new ToStringBuilder(this).append("method", getMethod().toGenericString()).toString(); } } DefaultMethodOrdererContext.java000066400000000000000000000032061455764576500370170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.MethodDescriptor; import org.junit.jupiter.api.MethodOrdererContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of {@link MethodOrdererContext}. * * @since 5.4 */ class DefaultMethodOrdererContext implements MethodOrdererContext { private final Class testClass; private final List methodDescriptors; private final JupiterConfiguration configuration; DefaultMethodOrdererContext(Class testClass, List methodDescriptors, JupiterConfiguration configuration) { this.testClass = testClass; this.methodDescriptors = methodDescriptors; this.configuration = configuration; } @Override public final Class getTestClass() { return this.testClass; } @Override public List getMethodDescriptors() { return this.methodDescriptors; } @Override public Optional getConfigurationParameter(String key) { return this.configuration.getRawConfigurationParameter(key); } @Override public String toString() { return new ToStringBuilder(this).append("testClass", this.testClass.getName()).toString(); } } DiscoverySelectorResolver.java000066400000000000000000000041421455764576500365740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; /** * {@code DiscoverySelectorResolver} resolves {@link TestDescriptor TestDescriptors} * for containers and tests selected by DiscoverySelectors with the help of the * {@code JavaElementsResolver}. * *

This class is the only public entry point into the discovery package. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class DiscoverySelectorResolver { // @formatter:off private static final EngineDiscoveryRequestResolver resolver = EngineDiscoveryRequestResolver.builder() .addClassContainerSelectorResolver(new IsTestClassWithTests()) .addSelectorResolver(context -> new ClassSelectorResolver(context.getClassNameFilter(), context.getEngineDescriptor().getConfiguration())) .addSelectorResolver(context -> new MethodSelectorResolver(context.getEngineDescriptor().getConfiguration())) .addTestDescriptorVisitor(context -> new ClassOrderingVisitor(context.getEngineDescriptor().getConfiguration())) .addTestDescriptorVisitor(context -> new MethodOrderingVisitor(context.getEngineDescriptor().getConfiguration())) .addTestDescriptorVisitor(context -> TestDescriptor::prune) .build(); // @formatter:on public void resolveSelectors(EngineDiscoveryRequest request, JupiterEngineDescriptor engineDescriptor) { resolver.resolve(request, engineDescriptor); } } MethodFinder.java000066400000000000000000000023301455764576500337470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import java.lang.reflect.Method; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ class MethodFinder { // Pattern: methodName(comma-separated list of parameter type names) private static final Pattern METHOD_PATTERN = Pattern.compile("(.+)\\((.*)\\)"); Optional findMethod(String methodSpecPart, Class clazz) { Matcher matcher = METHOD_PATTERN.matcher(methodSpecPart); Preconditions.condition(matcher.matches(), () -> String.format("Method [%s] does not match pattern [%s]", methodSpecPart, METHOD_PATTERN)); String methodName = matcher.group(1); String parameterTypeNames = matcher.group(2); return ReflectionUtils.findMethod(clazz, methodName, parameterTypeNames); } } MethodOrderingVisitor.java000066400000000000000000000065421455764576500357020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterTestDescriptor; import org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; /** * @since 5.5 */ class MethodOrderingVisitor extends AbstractOrderingVisitor { private final JupiterConfiguration configuration; MethodOrderingVisitor(JupiterConfiguration configuration) { this.configuration = configuration; } @Override public void visit(TestDescriptor testDescriptor) { doWithMatchingDescriptor(ClassBasedTestDescriptor.class, testDescriptor, descriptor -> orderContainedMethods(descriptor, descriptor.getTestClass()), descriptor -> "Failed to order methods for " + descriptor.getTestClass()); } /** * @since 5.4 */ private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescriptor, Class testClass) { findAnnotation(testClass, TestMethodOrder.class)// .map(TestMethodOrder::value)// . map(ReflectionUtils::newInstance)// .map(Optional::of)// .orElseGet(configuration::getDefaultTestMethodOrderer)// .ifPresent(methodOrderer -> { Consumer> orderingAction = methodDescriptors -> methodOrderer.orderMethods( new DefaultMethodOrdererContext(testClass, methodDescriptors, this.configuration)); MessageGenerator descriptorsAddedMessageGenerator = number -> String.format( "MethodOrderer [%s] added %s MethodDescriptor(s) for test class [%s] which will be ignored.", methodOrderer.getClass().getName(), number, testClass.getName()); MessageGenerator descriptorsRemovedMessageGenerator = number -> String.format( "MethodOrderer [%s] removed %s MethodDescriptor(s) for test class [%s] which will be retained with arbitrary ordering.", methodOrderer.getClass().getName(), number, testClass.getName()); DescriptorWrapperOrderer descriptorWrapperOrderer = new DescriptorWrapperOrderer(orderingAction, descriptorsAddedMessageGenerator, descriptorsRemovedMessageGenerator); orderChildrenTestDescriptors(classBasedTestDescriptor, // MethodBasedTestDescriptor.class, // DefaultMethodDescriptor::new, // descriptorWrapperOrderer); // Note: MethodOrderer#getDefaultExecutionMode() is guaranteed // to be invoked after MethodOrderer#orderMethods(). methodOrderer.getDefaultExecutionMode()// .map(JupiterTestDescriptor::toExecutionMode)// .ifPresent(classBasedTestDescriptor::setDefaultChildExecutionMode); }); } } MethodSelectorResolver.java000066400000000000000000000246731455764576500360600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.matches; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import java.lang.reflect.Method; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Stream; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor; import org.junit.jupiter.engine.descriptor.Filterable; import org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor; import org.junit.jupiter.engine.discovery.predicates.IsNestedTestClass; import org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests; import org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod; import org.junit.jupiter.engine.discovery.predicates.IsTestMethod; import org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.NestedMethodSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.discovery.SelectorResolver; /** * @since 5.5 */ class MethodSelectorResolver implements SelectorResolver { private static final Logger logger = LoggerFactory.getLogger(MethodSelectorResolver.class); private static final MethodFinder methodFinder = new MethodFinder(); private static final Predicate> testClassPredicate = new IsTestClassWithTests().or( new IsNestedTestClass()); protected final JupiterConfiguration configuration; MethodSelectorResolver(JupiterConfiguration configuration) { this.configuration = configuration; } @Override public Resolution resolve(MethodSelector selector, Context context) { return resolve(context, emptyList(), selector.getJavaClass(), selector::getJavaMethod, Match::exact); } @Override public Resolution resolve(NestedMethodSelector selector, Context context) { return resolve(context, selector.getEnclosingClasses(), selector.getNestedClass(), selector::getMethod, Match::exact); } private Resolution resolve(Context context, List> enclosingClasses, Class testClass, Supplier methodSupplier, BiFunction>, Match> matchFactory) { if (!testClassPredicate.test(testClass)) { return unresolved(); } Method method = methodSupplier.get(); // @formatter:off Set matches = Arrays.stream(MethodType.values()) .map(methodType -> methodType.resolve(enclosingClasses, testClass, method, context, configuration)) .filter(Optional::isPresent) .map(Optional::get) .map(testDescriptor -> matchFactory.apply(testDescriptor, expansionCallback(testDescriptor))) .collect(toSet()); // @formatter:on if (matches.size() > 1) { logger.warn(() -> { Stream testDescriptors = matches.stream().map(Match::getTestDescriptor); return String.format( "Possible configuration error: method [%s] resulted in multiple TestDescriptors %s. " + "This is typically the result of annotating a method with multiple competing annotations " + "such as @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, etc.", method.toGenericString(), testDescriptors.map(d -> d.getClass().getName()).collect(toList())); }); } return matches.isEmpty() ? unresolved() : matches(matches); } @Override public Resolution resolve(UniqueIdSelector selector, Context context) { UniqueId uniqueId = selector.getUniqueId(); // @formatter:off return Arrays.stream(MethodType.values()) .map(methodType -> methodType.resolveUniqueIdIntoTestDescriptor(uniqueId, context, configuration)) .filter(Optional::isPresent) .map(Optional::get) .map(testDescriptor -> { boolean exactMatch = uniqueId.equals(testDescriptor.getUniqueId()); if (testDescriptor instanceof Filterable) { Filterable filterable = (Filterable) testDescriptor; if (exactMatch) { filterable.getDynamicDescendantFilter().allowAll(); } else { filterable.getDynamicDescendantFilter().allowUniqueIdPrefix(uniqueId); } } return Resolution.match(exactMatch ? Match.exact(testDescriptor) : Match.partial(testDescriptor, expansionCallback(testDescriptor))); }) .findFirst() .orElse(unresolved()); // @formatter:on } @Override public Resolution resolve(IterationSelector selector, Context context) { if (selector.getParentSelector() instanceof MethodSelector) { MethodSelector methodSelector = (MethodSelector) selector.getParentSelector(); return resolve(context, emptyList(), methodSelector.getJavaClass(), methodSelector::getJavaMethod, (testDescriptor, childSelectorsSupplier) -> { if (testDescriptor instanceof Filterable) { Filterable filterable = (Filterable) testDescriptor; filterable.getDynamicDescendantFilter().allowIndex(selector.getIterationIndices()); } return Match.partial(testDescriptor, childSelectorsSupplier); }); } return unresolved(); } private Supplier> expansionCallback(TestDescriptor testDescriptor) { return () -> { if (testDescriptor instanceof Filterable) { Filterable filterable = (Filterable) testDescriptor; filterable.getDynamicDescendantFilter().allowAll(); } return emptySet(); }; } private enum MethodType { TEST(new IsTestMethod(), TestMethodTestDescriptor.SEGMENT_TYPE) { @Override protected TestDescriptor createTestDescriptor(UniqueId uniqueId, Class testClass, Method method, JupiterConfiguration configuration) { return new TestMethodTestDescriptor(uniqueId, testClass, method, configuration); } }, TEST_FACTORY(new IsTestFactoryMethod(), TestFactoryTestDescriptor.SEGMENT_TYPE, TestFactoryTestDescriptor.DYNAMIC_CONTAINER_SEGMENT_TYPE, TestFactoryTestDescriptor.DYNAMIC_TEST_SEGMENT_TYPE) { @Override protected TestDescriptor createTestDescriptor(UniqueId uniqueId, Class testClass, Method method, JupiterConfiguration configuration) { return new TestFactoryTestDescriptor(uniqueId, testClass, method, configuration); } }, TEST_TEMPLATE(new IsTestTemplateMethod(), TestTemplateTestDescriptor.SEGMENT_TYPE, TestTemplateInvocationTestDescriptor.SEGMENT_TYPE) { @Override protected TestDescriptor createTestDescriptor(UniqueId uniqueId, Class testClass, Method method, JupiterConfiguration configuration) { return new TestTemplateTestDescriptor(uniqueId, testClass, method, configuration); } }; private final Predicate methodPredicate; private final String segmentType; private final Set dynamicDescendantSegmentTypes; MethodType(Predicate methodPredicate, String segmentType, String... dynamicDescendantSegmentTypes) { this.methodPredicate = methodPredicate; this.segmentType = segmentType; this.dynamicDescendantSegmentTypes = new LinkedHashSet<>(Arrays.asList(dynamicDescendantSegmentTypes)); } private Optional resolve(List> enclosingClasses, Class testClass, Method method, Context context, JupiterConfiguration configuration) { if (!methodPredicate.test(method)) { return Optional.empty(); } return context.addToParent(() -> selectClass(enclosingClasses, testClass), // parent -> Optional.of( createTestDescriptor(createUniqueId(method, parent), testClass, method, configuration))); } private DiscoverySelector selectClass(List> enclosingClasses, Class testClass) { if (enclosingClasses.isEmpty()) { return DiscoverySelectors.selectClass(testClass); } return DiscoverySelectors.selectNestedClass(enclosingClasses, testClass); } private Optional resolveUniqueIdIntoTestDescriptor(UniqueId uniqueId, Context context, JupiterConfiguration configuration) { UniqueId.Segment lastSegment = uniqueId.getLastSegment(); if (segmentType.equals(lastSegment.getType())) { return context.addToParent(() -> selectUniqueId(uniqueId.removeLastSegment()), parent -> { String methodSpecPart = lastSegment.getValue(); Class testClass = ((ClassBasedTestDescriptor) parent).getTestClass(); // @formatter:off return methodFinder.findMethod(methodSpecPart, testClass) .filter(methodPredicate) .map(method -> createTestDescriptor(createUniqueId(method, parent), testClass, method, configuration)); // @formatter:on }); } if (dynamicDescendantSegmentTypes.contains(lastSegment.getType())) { return resolveUniqueIdIntoTestDescriptor(uniqueId.removeLastSegment(), context, configuration); } return Optional.empty(); } private UniqueId createUniqueId(Method method, TestDescriptor parent) { String methodId = String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); return parent.getUniqueId().append(segmentType, methodId); } protected abstract TestDescriptor createTestDescriptor(UniqueId uniqueId, Class testClass, Method method, JupiterConfiguration configuration); } } package-info.java000066400000000000000000000002531455764576500337250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/** * Internal classes for test discovery within the JUnit Jupiter test engine. * Contains resolvers for Java elements. */ package org.junit.jupiter.engine.discovery; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/000077500000000000000000000000001455764576500327405ustar00rootroot00000000000000IsInnerClass.java000066400000000000000000000021011455764576500360530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Test if a class is a non-private inner class (i.e., a non-static nested class). * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsInnerClass implements Predicate> { @Override public boolean test(Class candidate) { // Do not collapse into a single return statement. if (isPrivate(candidate)) { return false; } if (!isInnerClass(candidate)) { return false; } return true; } } IsNestedTestClass.java000066400000000000000000000021101455764576500370620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.jupiter.api.Nested; /** * Test if a class is a JUnit Jupiter {@link Nested @Nested} test class. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsNestedTestClass implements Predicate> { private static final IsInnerClass isInnerClass = new IsInnerClass(); @Override public boolean test(Class candidate) { //please do not collapse into single return if (!isInnerClass.test(candidate)) { return false; } return isAnnotated(candidate, Nested.class); } } IsPotentialTestContainer.java000066400000000000000000000025041455764576500404630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.isAbstract; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Test if a class is a potential top-level JUnit Jupiter test container, even if * it does not contain tests. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsPotentialTestContainer implements Predicate> { @Override public boolean test(Class candidate) { // Please do not collapse the following into a single statement. if (isPrivate(candidate)) { return false; } if (isAbstract(candidate)) { return false; } if (candidate.isLocalClass()) { return false; } if (candidate.isAnonymousClass()) { return false; } return !isInnerClass(candidate); } } IsTestClassWithTests.java000066400000000000000000000036641455764576500376150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Method; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.ReflectionUtils; /** * Test if a class is a JUnit Jupiter test class containing executable tests, * test factories, test templates, or nested tests. * * @since 5.0 */ @API(status = INTERNAL, since = "5.1") public class IsTestClassWithTests implements Predicate> { private static final IsTestMethod isTestMethod = new IsTestMethod(); private static final IsTestFactoryMethod isTestFactoryMethod = new IsTestFactoryMethod(); private static final IsTestTemplateMethod isTestTemplateMethod = new IsTestTemplateMethod(); public static final Predicate isTestOrTestFactoryOrTestTemplateMethod = isTestMethod.or( isTestFactoryMethod).or(isTestTemplateMethod); private static final IsPotentialTestContainer isPotentialTestContainer = new IsPotentialTestContainer(); private static final IsNestedTestClass isNestedTestClass = new IsNestedTestClass(); @Override public boolean test(Class candidate) { return isPotentialTestContainer.test(candidate) && (hasTestOrTestFactoryOrTestTemplateMethods(candidate) || hasNestedTests(candidate)); } private boolean hasTestOrTestFactoryOrTestTemplateMethods(Class candidate) { return ReflectionUtils.isMethodPresent(candidate, isTestOrTestFactoryOrTestTemplateMethod); } private boolean hasNestedTests(Class candidate) { return !ReflectionUtils.findNestedClasses(candidate, isNestedTestClass).isEmpty(); } } IsTestFactoryMethod.java000066400000000000000000000016451455764576500374360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.TestFactory; /** * Test if a method is a JUnit Jupiter {@link TestFactory @TestFactory} method. * *

NOTE: this predicate does not check if a candidate method * has an appropriate return type for a {@code @TestFactory} method. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsTestFactoryMethod extends IsTestableMethod { public IsTestFactoryMethod() { super(TestFactory.class, false); } } IsTestMethod.java000066400000000000000000000013411455764576500360770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.Test; /** * Test if a method is a JUnit Jupiter {@link Test @Test} method. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsTestMethod extends IsTestableMethod { public IsTestMethod() { super(Test.class, true); } } IsTestTemplateMethod.java000066400000000000000000000014211455764576500375720ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.TestTemplate; /** * Test if a method is a JUnit Jupiter {@link TestTemplate @TestTemplate} method. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class IsTestTemplateMethod extends IsTestableMethod { public IsTestTemplateMethod() { super(TestTemplate.class, true); } } IsTestableMethod.java000066400000000000000000000031221455764576500367220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import static org.junit.platform.commons.util.ReflectionUtils.isAbstract; import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; import static org.junit.platform.commons.util.ReflectionUtils.isStatic; import static org.junit.platform.commons.util.ReflectionUtils.returnsVoid; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.function.Predicate; /** * @since 5.0 */ abstract class IsTestableMethod implements Predicate { private final Class annotationType; private final boolean mustReturnVoid; IsTestableMethod(Class annotationType, boolean mustReturnVoid) { this.annotationType = annotationType; this.mustReturnVoid = mustReturnVoid; } @Override public boolean test(Method candidate) { // Please do not collapse the following into a single statement. if (isStatic(candidate)) { return false; } if (isPrivate(candidate)) { return false; } if (isAbstract(candidate)) { return false; } if (returnsVoid(candidate) != this.mustReturnVoid) { return false; } return isAnnotated(candidate, this.annotationType); } } package-info.java000066400000000000000000000002331455764576500360460ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/** * Internal predicate classes used by test discovery within the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.discovery.predicates; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/000077500000000000000000000000001455764576500306115ustar00rootroot00000000000000AfterEachMethodAdapter.java000066400000000000000000000017631455764576500356700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; /** * Functional interface for registering an {@link AfterEach @AfterEach} method * as a pseudo-extension. * * @since 5.0 */ @FunctionalInterface @API(status = INTERNAL, since = "5.0") public interface AfterEachMethodAdapter extends Extension { void invokeAfterEachMethod(ExtensionContext context, ExtensionRegistry registry) throws Throwable; } BeforeEachMethodAdapter.java000066400000000000000000000017671455764576500360350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; /** * Functional interface for registering a {@link BeforeEach @BeforeEach} method * as a pseudo-extension. * * @since 5.0 */ @FunctionalInterface @API(status = INTERNAL, since = "5.0") public interface BeforeEachMethodAdapter extends Extension { void invokeBeforeEachMethod(ExtensionContext context, ExtensionRegistry registry) throws Throwable; } ConditionEvaluationException.java000066400000000000000000000014711455764576500372350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered while evaluating an * {@link ExecutionCondition}. * * @since 5.0 * @see ConditionEvaluator */ class ConditionEvaluationException extends JUnitException { private static final long serialVersionUID = 1L; public ConditionEvaluationException(String message, Throwable cause) { super(message, cause); } } ConditionEvaluator.java000066400000000000000000000061161455764576500352120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.StringUtils; /** * {@code ConditionEvaluator} evaluates {@link ExecutionCondition} extensions. * * @since 5.0 * @see ExecutionCondition */ @API(status = INTERNAL, since = "5.0") public class ConditionEvaluator { private static final Logger logger = LoggerFactory.getLogger(ConditionEvaluator.class); private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "No 'disabled' conditions encountered"); /** * Evaluate all {@link ExecutionCondition} extensions registered for the * supplied {@link ExtensionContext}. * * @param context the current {@code ExtensionContext} * @return the first disabled {@code ConditionEvaluationResult}, * or a default enabled {@code ConditionEvaluationResult} if no * disabled conditions are encountered */ public ConditionEvaluationResult evaluate(ExtensionRegistry extensionRegistry, JupiterConfiguration configuration, ExtensionContext context) { // @formatter:off return extensionRegistry.stream(ExecutionCondition.class) .filter(configuration.getExecutionConditionFilter()) .map(condition -> evaluate(condition, context)) .filter(ConditionEvaluationResult::isDisabled) .findFirst() .orElse(ENABLED); // @formatter:on } private ConditionEvaluationResult evaluate(ExecutionCondition condition, ExtensionContext context) { try { ConditionEvaluationResult result = condition.evaluateExecutionCondition(context); logResult(condition.getClass(), result, context); return result; } catch (Exception ex) { throw evaluationException(condition.getClass(), ex); } } private void logResult(Class conditionType, ConditionEvaluationResult result, ExtensionContext context) { logger.trace(() -> format("Evaluation of condition [%s] on [%s] resulted in: %s", conditionType.getName(), context.getElement().get(), result)); } private ConditionEvaluationException evaluationException(Class conditionType, Exception ex) { String cause = StringUtils.isNotBlank(ex.getMessage()) ? ": " + ex.getMessage() : ""; return new ConditionEvaluationException( format("Failed to evaluate condition [%s]%s", conditionType.getName(), cause), ex); } } ConstructorInvocation.java000066400000000000000000000027771455764576500357710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static java.util.Collections.unmodifiableList; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.platform.commons.util.ReflectionUtils; class ConstructorInvocation implements Invocation, ReflectiveInvocationContext> { private final Constructor constructor; private final Object[] arguments; ConstructorInvocation(Constructor constructor, Object[] arguments) { this.constructor = constructor; this.arguments = arguments; } @Override public Class getTargetClass() { return this.constructor.getDeclaringClass(); } @Override public Constructor getExecutable() { return this.constructor; } @Override public List getArguments() { return unmodifiableList(Arrays.asList(this.arguments)); } @Override public Optional getTarget() { return Optional.empty(); } @Override public T proceed() { return ReflectionUtils.newInstance(this.constructor, this.arguments); } } DefaultExecutableInvoker.java000066400000000000000000000037341455764576500363300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.execution.ParameterResolutionUtils.resolveParameters; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.9 */ @API(status = INTERNAL, since = "5.9") public class DefaultExecutableInvoker implements ExecutableInvoker { private final ExtensionContext extensionContext; private final ExtensionRegistry extensionRegistry; public DefaultExecutableInvoker(ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { this.extensionContext = extensionContext; this.extensionRegistry = extensionRegistry; } public DefaultExecutableInvoker(JupiterEngineExecutionContext context) { this(context.getExtensionContext(), context.getExtensionRegistry()); } @Override public T invoke(Constructor constructor, Object outerInstance) { Object[] arguments = resolveParameters(constructor, Optional.empty(), Optional.ofNullable(outerInstance), extensionContext, extensionRegistry); return ReflectionUtils.newInstance(constructor, arguments); } @Override public Object invoke(Method method, Object target) { Object[] arguments = resolveParameters(method, Optional.ofNullable(target), extensionContext, extensionRegistry); return ReflectionUtils.invokeMethod(method, target, arguments); } } DefaultParameterContext.java000066400000000000000000000043321455764576500361710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import java.lang.annotation.Annotation; import java.lang.reflect.Parameter; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * @since 5.0 */ class DefaultParameterContext implements ParameterContext { private final Parameter parameter; private final int index; private final Optional target; DefaultParameterContext(Parameter parameter, int index, Optional target) { Preconditions.condition(index >= 0, "index must be greater than or equal to zero"); this.parameter = Preconditions.notNull(parameter, "parameter must not be null"); this.index = index; this.target = Preconditions.notNull(target, "target must not be null"); } @Override public Parameter getParameter() { return this.parameter; } @Override public int getIndex() { return this.index; } @Override public Optional getTarget() { return this.target; } @Override public boolean isAnnotated(Class annotationType) { return AnnotationUtils.isAnnotated(this.parameter, this.index, annotationType); } @Override public Optional findAnnotation(Class annotationType) { return AnnotationUtils.findAnnotation(this.parameter, this.index, annotationType); } @Override public List findRepeatableAnnotations(Class annotationType) { return AnnotationUtils.findRepeatableAnnotations(this.parameter, this.index, annotationType); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("parameter", this.parameter) .append("index", this.index) .append("target", this.target) .toString(); // @formatter:on } } DefaultTestInstances.java000066400000000000000000000041161455764576500354730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.TestInstances; import org.junit.platform.commons.util.Preconditions; @API(status = INTERNAL, since = "5.4") public class DefaultTestInstances implements TestInstances { public static DefaultTestInstances of(Object instance) { return new DefaultTestInstances(Collections.singletonList(instance)); } public static DefaultTestInstances of(TestInstances testInstances, Object instance) { List allInstances = new ArrayList<>(testInstances.getAllInstances()); allInstances.add(instance); return new DefaultTestInstances(Collections.unmodifiableList(allInstances)); } private final List instances; private DefaultTestInstances(List instances) { this.instances = Preconditions.notEmpty(instances, "instances must not be empty"); } @Override public Object getInnermostInstance() { return instances.get(instances.size() - 1); } @Override public List getEnclosingInstances() { return instances.subList(0, instances.size() - 1); } @Override public List getAllInstances() { return instances; } @Override public Optional findInstance(Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); ListIterator iterator = instances.listIterator(instances.size()); while (iterator.hasPrevious()) { Object instance = iterator.previous(); if (requiredType.isInstance(instance)) { return Optional.of(requiredType.cast(instance)); } } return Optional.empty(); } } InterceptingExecutableInvoker.java000066400000000000000000000122221455764576500373670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.execution.ParameterResolutionUtils.resolveParameters; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; /** * {@code InterceptingExecutableInvoker} encapsulates the invocation of a * {@link java.lang.reflect.Executable} (i.e., method or constructor), * including support for dynamic resolution of method parameters via * {@link ParameterResolver ParameterResolvers}. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class InterceptingExecutableInvoker { private static final InvocationInterceptorChain interceptorChain = new InvocationInterceptorChain(); /** * Invoke the supplied constructor with the supplied outer instance and * dynamic parameter resolution. * * @param constructor the constructor to invoke and resolve parameters for * @param outerInstance the outer instance to supply as the first argument * to the constructor; empty, for top-level classes * @param extensionContext the current {@code ExtensionContext} * @param extensionRegistry the {@code ExtensionRegistry} to retrieve * {@code ParameterResolvers} from * @param interceptorCall the call for intercepting this constructor * invocation via all registered {@linkplain InvocationInterceptor * interceptors} */ public T invoke(Constructor constructor, Optional outerInstance, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall, T> interceptorCall) { Object[] arguments = resolveParameters(constructor, Optional.empty(), outerInstance, extensionContext, extensionRegistry); ConstructorInvocation invocation = new ConstructorInvocation<>(constructor, arguments); return invoke(invocation, invocation, extensionContext, extensionRegistry, interceptorCall); } /** * Invoke the supplied method with dynamic parameter resolution. * * @param method the method to invoke and resolve parameters for * @param target the target on which the executable will be invoked, * potentially wrapped in an {@link Optional}; can be {@code null} or an * empty {@code Optional} for a {@code static} method * @param extensionContext the current {@code ExtensionContext} * @param extensionRegistry the {@code ExtensionRegistry} to retrieve * {@code ParameterResolvers} from * @param interceptorCall the call for intercepting this method invocation * via all registered {@linkplain InvocationInterceptor interceptors} */ public T invoke(Method method, Object target, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall interceptorCall) { @SuppressWarnings("unchecked") Optional optionalTarget = (target instanceof Optional ? (Optional) target : Optional.ofNullable(target)); Object[] arguments = resolveParameters(method, optionalTarget, extensionContext, extensionRegistry); MethodInvocation invocation = new MethodInvocation<>(method, optionalTarget, arguments); return invoke(invocation, invocation, extensionContext, extensionRegistry, interceptorCall); } private T invoke(Invocation originalInvocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall call) { return interceptorChain.invoke(originalInvocation, extensionRegistry, (interceptor, wrappedInvocation) -> call.apply(interceptor, wrappedInvocation, invocationContext, extensionContext)); } public interface ReflectiveInterceptorCall { T apply(InvocationInterceptor interceptor, Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable; static ReflectiveInterceptorCall ofVoidMethod(VoidMethodInterceptorCall call) { return ((interceptorChain, invocation, invocationContext, extensionContext) -> { call.apply(interceptorChain, invocation, invocationContext, extensionContext); return null; }); } interface VoidMethodInterceptorCall { void apply(InvocationInterceptor interceptor, Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable; } } } InvocationInterceptorChain.java000066400000000000000000000115761455764576500367020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.List; import java.util.ListIterator; import java.util.concurrent.atomic.AtomicBoolean; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ExceptionUtils; @API(status = INTERNAL, since = "5.5") public class InvocationInterceptorChain { public T invoke(Invocation invocation, ExtensionRegistry extensionRegistry, InterceptorCall call) { List interceptors = extensionRegistry.getExtensions(InvocationInterceptor.class); if (interceptors.isEmpty()) { return proceed(invocation); } return chainAndInvoke(invocation, call, interceptors); } private T chainAndInvoke(Invocation invocation, InterceptorCall call, List interceptors) { ValidatingInvocation validatingInvocation = new ValidatingInvocation<>(invocation, interceptors); Invocation chainedInvocation = chainInterceptors(validatingInvocation, call, interceptors); T result = proceed(chainedInvocation); validatingInvocation.verifyInvokedAtLeastOnce(); return result; } private Invocation chainInterceptors(Invocation invocation, InterceptorCall call, List interceptors) { Invocation result = invocation; ListIterator iterator = interceptors.listIterator(interceptors.size()); while (iterator.hasPrevious()) { InvocationInterceptor interceptor = iterator.previous(); result = new InterceptedInvocation<>(result, call, interceptor); } return result; } private T proceed(Invocation invocation) { try { return invocation.proceed(); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(t); } } @FunctionalInterface public interface InterceptorCall { T apply(InvocationInterceptor interceptor, Invocation invocation) throws Throwable; static InterceptorCall ofVoid(VoidInterceptorCall call) { return ((interceptorChain, invocation) -> { call.apply(interceptorChain, invocation); return null; }); } } @FunctionalInterface public interface VoidInterceptorCall { void apply(InvocationInterceptor interceptor, Invocation invocation) throws Throwable; } private static class InterceptedInvocation implements Invocation { private final Invocation invocation; private final InterceptorCall call; private final InvocationInterceptor interceptor; InterceptedInvocation(Invocation invocation, InterceptorCall call, InvocationInterceptor interceptor) { this.invocation = invocation; this.call = call; this.interceptor = interceptor; } @Override public T proceed() throws Throwable { return call.apply(interceptor, invocation); } @Override public void skip() { invocation.skip(); } } private static class ValidatingInvocation implements Invocation { private static final Logger logger = LoggerFactory.getLogger(ValidatingInvocation.class); private final AtomicBoolean invokedOrSkipped = new AtomicBoolean(); private final Invocation delegate; private final List interceptors; ValidatingInvocation(Invocation delegate, List interceptors) { this.delegate = delegate; this.interceptors = interceptors; } @Override public T proceed() throws Throwable { markInvokedOrSkipped(); return delegate.proceed(); } @Override public void skip() { logger.debug(() -> "The invocation is skipped"); markInvokedOrSkipped(); delegate.skip(); } private void markInvokedOrSkipped() { if (!invokedOrSkipped.compareAndSet(false, true)) { fail("Chain of InvocationInterceptors called invocation multiple times instead of just once"); } } void verifyInvokedAtLeastOnce() { if (!invokedOrSkipped.get()) { fail("Chain of InvocationInterceptors never called invocation"); } } private void fail(String prefix) { String commaSeparatedInterceptorClasses = interceptors.stream().map(Object::getClass).map( Class::getName).collect(joining(", ")); throw new JUnitException(prefix + ": " + commaSeparatedInterceptorClasses); } } } JupiterEngineExecutionContext.java000066400000000000000000000124731455764576500374050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class JupiterEngineExecutionContext implements EngineExecutionContext { private static final Logger logger = LoggerFactory.getLogger(JupiterEngineExecutionContext.class); private final State state; // The following is not "cloneable" State. private boolean beforeAllCallbacksExecuted = false; private boolean beforeAllMethodsExecuted = false; public JupiterEngineExecutionContext(EngineExecutionListener executionListener, JupiterConfiguration configuration) { this(new State(executionListener, configuration)); } private JupiterEngineExecutionContext(State state) { this.state = state; } public void close() throws Exception { ExtensionContext extensionContext = getExtensionContext(); if (extensionContext instanceof AutoCloseable) { try { ((AutoCloseable) extensionContext).close(); } catch (Exception e) { logger.error(e, () -> "Caught exception while closing extension context: " + extensionContext); throw e; } } } public EngineExecutionListener getExecutionListener() { return this.state.executionListener; } public JupiterConfiguration getConfiguration() { return this.state.configuration; } public TestInstancesProvider getTestInstancesProvider() { return this.state.testInstancesProvider; } public MutableExtensionRegistry getExtensionRegistry() { return this.state.extensionRegistry; } public ExtensionContext getExtensionContext() { return this.state.extensionContext; } public ThrowableCollector getThrowableCollector() { return this.state.throwableCollector; } /** * Track that an attempt was made to execute {@code BeforeAllCallback} extensions. * * @since 5.3 */ public void beforeAllCallbacksExecuted(boolean beforeAllCallbacksExecuted) { this.beforeAllCallbacksExecuted = beforeAllCallbacksExecuted; } /** * @return {@code true} if an attempt was made to execute {@code BeforeAllCallback} * extensions * @since 5.3 */ public boolean beforeAllCallbacksExecuted() { return beforeAllCallbacksExecuted; } /** * Track that an attempt was made to execute {@code @BeforeAll} methods. */ public void beforeAllMethodsExecuted(boolean beforeAllMethodsExecuted) { this.beforeAllMethodsExecuted = beforeAllMethodsExecuted; } /** * @return {@code true} if an attempt was made to execute {@code @BeforeAll} * methods */ public boolean beforeAllMethodsExecuted() { return this.beforeAllMethodsExecuted; } public Builder extend() { return new Builder(this.state); } private static final class State implements Cloneable { final EngineExecutionListener executionListener; final JupiterConfiguration configuration; TestInstancesProvider testInstancesProvider; MutableExtensionRegistry extensionRegistry; ExtensionContext extensionContext; ThrowableCollector throwableCollector; State(EngineExecutionListener executionListener, JupiterConfiguration configuration) { this.executionListener = executionListener; this.configuration = configuration; } @Override public State clone() { try { return (State) super.clone(); } catch (CloneNotSupportedException e) { throw new JUnitException("State could not be cloned", e); } } } public static class Builder { private State originalState; private State newState = null; private Builder(State originalState) { this.originalState = originalState; } public Builder withTestInstancesProvider(TestInstancesProvider testInstancesProvider) { newState().testInstancesProvider = testInstancesProvider; return this; } public Builder withExtensionRegistry(MutableExtensionRegistry extensionRegistry) { newState().extensionRegistry = extensionRegistry; return this; } public Builder withExtensionContext(ExtensionContext extensionContext) { newState().extensionContext = extensionContext; return this; } public Builder withThrowableCollector(ThrowableCollector throwableCollector) { newState().throwableCollector = throwableCollector; return this; } public JupiterEngineExecutionContext build() { if (newState != null) { originalState = newState; newState = null; } return new JupiterEngineExecutionContext(originalState); } private State newState() { if (newState == null) { this.newState = originalState.clone(); } return newState; } } } MethodInvocation.java000066400000000000000000000032271455764576500346530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static java.util.Collections.unmodifiableList; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.platform.commons.util.ReflectionUtils; class MethodInvocation implements Invocation, ReflectiveInvocationContext { private final Method method; private final Optional target; private final Object[] arguments; MethodInvocation(Method method, Optional target, Object[] arguments) { this.method = method; this.target = target; this.arguments = arguments; } @Override public Class getTargetClass() { return this.target.> map(Object::getClass).orElseGet(this.method::getDeclaringClass); } @Override @SuppressWarnings("unchecked") public Optional getTarget() { return this.target; } @Override public Method getExecutable() { return this.method; } @Override public List getArguments() { return unmodifiableList(Arrays.asList(this.arguments)); } @Override @SuppressWarnings("unchecked") public T proceed() { return (T) ReflectionUtils.invokeMethod(this.method, this.target.orElse(null), this.arguments); } } NamespaceAwareStore.java000066400000000000000000000065361455764576500353000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.function.Function; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ExtensionContextException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; import org.junit.platform.engine.support.store.NamespacedHierarchicalStoreException; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class NamespaceAwareStore implements Store { private final NamespacedHierarchicalStore valuesStore; private final Namespace namespace; public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, Namespace namespace) { this.valuesStore = valuesStore; this.namespace = namespace; } @Override public Object get(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.get(this.namespace, key)); } @Override public T get(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore(() -> this.valuesStore.get(this.namespace, key, requiredType)); } @Override public Object getOrComputeIfAbsent(K key, Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); return accessStore(() -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator)); } @Override public V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore( () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator, requiredType)); } @Override public void put(Object key, Object value) { Preconditions.notNull(key, "key must not be null"); accessStore(() -> this.valuesStore.put(this.namespace, key, value)); } @Override public Object remove(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key)); } @Override public T remove(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key, requiredType)); } private T accessStore(Supplier action) { try { return action.get(); } catch (NamespacedHierarchicalStoreException e) { throw new ExtensionContextException(e.getMessage(), e); } } } ParameterResolutionUtils.java000066400000000000000000000173631455764576500364340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * {@code ParameterResolutionUtils} provides support for dynamic resolution * of executable parameters via {@link ParameterResolver ParameterResolvers}. * * @since 5.9 */ @API(status = INTERNAL, since = "5.9") public class ParameterResolutionUtils { private static final Logger logger = LoggerFactory.getLogger(ParameterResolutionUtils.class); /** * Resolve the array of parameters for the supplied method and target. * * @param method the method for which to resolve parameters * @param target an {@code Optional} containing the target on which the * executable will be invoked; never {@code null} but should be empty for * static methods and constructors * @param extensionContext the current {@code ExtensionContext} * @param extensionRegistry the {@code ExtensionRegistry} to retrieve * {@code ParameterResolvers} from * @return the array of Objects to be used as parameters in the executable * invocation; never {@code null} though potentially empty */ public static Object[] resolveParameters(Method method, Optional target, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { return resolveParameters(method, target, Optional.empty(), extensionContext, extensionRegistry); } /** * Resolve the array of parameters for the supplied executable, target, and * outer instance. * * @param executable the executable for which to resolve parameters * @param target an {@code Optional} containing the target on which the * executable will be invoked; never {@code null} but should be empty for * static methods and constructors * @param outerInstance the outer instance that will be supplied as the * first argument to a constructor for an inner class; should be {@code null} * for methods and constructors for top-level or static classes * @param extensionContext the current {@code ExtensionContext} * @param extensionRegistry the {@code ExtensionRegistry} to retrieve * {@code ParameterResolvers} from * @return the array of Objects to be used as parameters in the executable * invocation; never {@code null} though potentially empty */ public static Object[] resolveParameters(Executable executable, Optional target, Optional outerInstance, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { Preconditions.notNull(target, "target must not be null"); Parameter[] parameters = executable.getParameters(); Object[] values = new Object[parameters.length]; int start = 0; // Ensure that the outer instance is resolved as the first parameter if // the executable is a constructor for an inner class. if (outerInstance.isPresent()) { values[0] = outerInstance.get(); start = 1; } // Resolve remaining parameters dynamically for (int i = start; i < parameters.length; i++) { ParameterContext parameterContext = new DefaultParameterContext(parameters[i], i, target); values[i] = resolveParameter(parameterContext, executable, extensionContext, extensionRegistry); } return values; } private static Object resolveParameter(ParameterContext parameterContext, Executable executable, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { try { // @formatter:off List matchingResolvers = extensionRegistry.stream(ParameterResolver.class) .filter(resolver -> resolver.supportsParameter(parameterContext, extensionContext)) .collect(toList()); // @formatter:on if (matchingResolvers.isEmpty()) { throw new ParameterResolutionException( String.format("No ParameterResolver registered for parameter [%s] in %s [%s].", parameterContext.getParameter(), asLabel(executable), executable.toGenericString())); } if (matchingResolvers.size() > 1) { // @formatter:off String resolvers = matchingResolvers.stream() .map(StringUtils::defaultToString) .collect(joining(", ")); // @formatter:on throw new ParameterResolutionException( String.format("Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s", parameterContext.getParameter(), asLabel(executable), executable.toGenericString(), resolvers)); } ParameterResolver resolver = matchingResolvers.get(0); Object value = resolver.resolveParameter(parameterContext, extensionContext); validateResolvedType(parameterContext.getParameter(), value, executable, resolver); logger.trace(() -> String.format( "ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s].", resolver.getClass().getName(), (value != null ? value.getClass().getName() : null), parameterContext.getParameter(), asLabel(executable), executable.toGenericString())); return value; } catch (ParameterResolutionException ex) { throw ex; } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); String message = String.format("Failed to resolve parameter [%s] in %s [%s]", parameterContext.getParameter(), asLabel(executable), executable.toGenericString()); if (StringUtils.isNotBlank(throwable.getMessage())) { message += ": " + throwable.getMessage(); } throw new ParameterResolutionException(message, throwable); } } private static void validateResolvedType(Parameter parameter, Object value, Executable executable, ParameterResolver resolver) { Class type = parameter.getType(); // Note: null is permissible as a resolved value but only for non-primitive types. if (!isAssignableTo(value, type)) { String message; if (value == null && type.isPrimitive()) { message = String.format( "ParameterResolver [%s] resolved a null value for parameter [%s] " + "in %s [%s], but a primitive of type [%s] is required.", resolver.getClass().getName(), parameter, asLabel(executable), executable.toGenericString(), type.getName()); } else { message = String.format( "ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] " + "in %s [%s], but a value assignment compatible with [%s] is required.", resolver.getClass().getName(), (value != null ? value.getClass().getName() : null), parameter, asLabel(executable), executable.toGenericString(), type.getName()); } throw new ParameterResolutionException(message); } } private static String asLabel(Executable executable) { return executable instanceof Constructor ? "constructor" : "method"; } } TestInstancesProvider.java000066400000000000000000000023571455764576500357060ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.engine.extension.ExtensionRegistrar; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * @since 5.0 */ @FunctionalInterface @API(status = INTERNAL, since = "5.0") public interface TestInstancesProvider { default TestInstances getTestInstances(MutableExtensionRegistry extensionRegistry, ThrowableCollector throwableCollector) { return getTestInstances(extensionRegistry, extensionRegistry, throwableCollector); } TestInstances getTestInstances(ExtensionRegistry extensionRegistry, ExtensionRegistrar extensionRegistrar, ThrowableCollector throwableCollector); } package-info.java000066400000000000000000000002021455764576500337130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/** * Internal classes for test execution within the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.execution; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/000077500000000000000000000000001455764576500306225ustar00rootroot00000000000000DefaultRepetitionInfo.java000066400000000000000000000033061455764576500356530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.RepetitionInfo; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of {@link RepetitionInfo}. */ class DefaultRepetitionInfo implements RepetitionInfo { final int currentRepetition; final int totalRepetitions; final AtomicInteger failureCount; final int failureThreshold; DefaultRepetitionInfo(int currentRepetition, int totalRepetitions, AtomicInteger failureCount, int failureThreshold) { this.currentRepetition = currentRepetition; this.totalRepetitions = totalRepetitions; this.failureCount = failureCount; this.failureThreshold = failureThreshold; } @Override public int getCurrentRepetition() { return this.currentRepetition; } @Override public int getTotalRepetitions() { return this.totalRepetitions; } @Override public int getFailureCount() { return this.failureCount.get(); } @Override public int getFailureThreshold() { return this.failureThreshold; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("currentRepetition", this.currentRepetition) .append("totalRepetitions", this.totalRepetitions) .append("failureCount", this.failureCount) .append("failureThreshold", this.failureThreshold) .toString(); // @formatter:on } } DisabledCondition.java000066400000000000000000000034031455764576500347640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.reflect.AnnotatedElement; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.util.StringUtils; /** * {@link ExecutionCondition} that supports the {@code @Disabled} annotation. * * @since 5.0 * @see Disabled * @see #evaluateExecutionCondition(ExtensionContext) */ class DisabledCondition implements ExecutionCondition { private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( "@Disabled is not present"); /** * Containers/tests are disabled if {@code @Disabled} is present on the test * class or method. */ @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { AnnotatedElement element = context.getElement().orElse(null); return findAnnotation(element, Disabled.class) // .map(annotation -> toResult(element, annotation)) // .orElse(ENABLED); } private ConditionEvaluationResult toResult(AnnotatedElement element, Disabled annotation) { String value = annotation.value(); String reason = StringUtils.isNotBlank(value) ? value : element + " is @Disabled"; return ConditionEvaluationResult.disabled(reason); } } ExtensionRegistrar.java000066400000000000000000000051171455764576500352510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.Extension; /** * An {@code ExtensionRegistrar} is used to register extensions. * * @since 5.5 */ @API(status = INTERNAL, since = "5.5") public interface ExtensionRegistrar { /** * Instantiate an extension of the given type using its default constructor * and register it in the registry. * *

A new {@link Extension} should not be registered if an extension of the * given type already exists in the registry or a parent registry. * * @param extensionType the type of extension to register * @since 5.8 */ void registerExtension(Class extensionType); /** * Register the supplied {@link Extension}, without checking if an extension * of that type has already been registered. * *

Semantics for Source

* *

If an extension is registered declaratively via * {@link org.junit.jupiter.api.extension.ExtendWith @ExtendWith}, the * {@code source} and the {@code extension} should be the same object. * However, if an extension is registered programmatically via * {@link org.junit.jupiter.api.extension.RegisterExtension @RegisterExtension}, * the {@code source} object should be the {@link java.lang.reflect.Field} * that is annotated with {@code @RegisterExtension}. Similarly, if an * extension is registered programmatically as a lambda expression * or method reference, the {@code source} object should be the underlying * {@link java.lang.reflect.Method} that implements the extension API. * * @param extension the extension to register; never {@code null} * @param source the source of the extension; never {@code null} */ void registerExtension(Extension extension, Object source); /** * Register the supplied {@link Extension} as a synthetic extension, * without checking if an extension of that type has already been registered. * * @param extension the extension to register; never {@code null} * @param source the source of the extension; never {@code null} * @since 5.8 * @see #registerExtension(Extension, Object) */ void registerSyntheticExtension(Extension extension, Object source); } ExtensionRegistry.java000066400000000000000000000030641455764576500351160ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.stream.Collectors.toCollection; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.Extension; /** * An {@code ExtensionRegistry} holds all registered extensions (i.e. * instances of {@link Extension}) for a given * {@link org.junit.platform.engine.support.hierarchical.Node}. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public interface ExtensionRegistry { /** * Stream all {@code Extensions} of the specified type that are present * in this registry or one of its ancestors. * * @param extensionType the type of {@link Extension} to stream * @see #getExtensions(Class) */ Stream stream(Class extensionType); /** * Get all {@code Extensions} of the specified type that are present * in this registry or one of its ancestors. * * @param extensionType the type of {@link Extension} to get * @see #stream(Class) */ default List getExtensions(Class extensionType) { return stream(extensionType).collect(toCollection(ArrayList::new)); } } MutableExtensionRegistry.java000066400000000000000000000161111455764576500364250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.stream.Stream.concat; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.ServiceLoader; import java.util.Set; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * Default, mutable implementation of {@link ExtensionRegistry}. * *

A registry has a reference to its parent registry, and all lookups are * performed first in the current registry itself and then recursively in its * ancestors. * * @since 5.5 */ @API(status = INTERNAL, since = "5.5") public class MutableExtensionRegistry implements ExtensionRegistry, ExtensionRegistrar { private static final Logger logger = LoggerFactory.getLogger(MutableExtensionRegistry.class); private static final List DEFAULT_STATELESS_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(// new DisabledCondition(), // new TimeoutExtension(), // new RepeatedTestExtension(), // new TestInfoParameterResolver(), // new TestReporterParameterResolver())); /** * Factory for creating and populating a new root registry with the default * extensions. * *

If the {@link org.junit.jupiter.engine.Constants#EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME} * configuration parameter has been set to {@code true}, extensions will be * auto-detected using Java's {@link ServiceLoader} mechanism and automatically * registered after the default extensions. * * @param configuration configuration parameters used to retrieve the extension * auto-detection flag; never {@code null} * @return a new {@code ExtensionRegistry}; never {@code null} */ public static MutableExtensionRegistry createRegistryWithDefaultExtensions(JupiterConfiguration configuration) { MutableExtensionRegistry extensionRegistry = new MutableExtensionRegistry(null); DEFAULT_STATELESS_EXTENSIONS.forEach(extensionRegistry::registerDefaultExtension); extensionRegistry.registerDefaultExtension(new TempDirectory(configuration)); if (configuration.isExtensionAutoDetectionEnabled()) { registerAutoDetectedExtensions(extensionRegistry); } return extensionRegistry; } private static void registerAutoDetectedExtensions(MutableExtensionRegistry extensionRegistry) { ServiceLoader.load(Extension.class, ClassLoaderUtils.getDefaultClassLoader())// .forEach(extensionRegistry::registerAutoDetectedExtension); } /** * Factory for creating and populating a new registry from a list of * extension types and a parent registry. * * @param parentRegistry the parent registry * @param extensionTypes the types of extensions to be registered in * the new registry * @return a new {@code ExtensionRegistry}; never {@code null} */ public static MutableExtensionRegistry createRegistryFrom(MutableExtensionRegistry parentRegistry, Stream> extensionTypes) { Preconditions.notNull(parentRegistry, "parentRegistry must not be null"); MutableExtensionRegistry registry = new MutableExtensionRegistry(parentRegistry); extensionTypes.forEach(registry::registerExtension); return registry; } private final MutableExtensionRegistry parent; private final Set> registeredExtensionTypes = new LinkedHashSet<>(); private final List registeredExtensions = new ArrayList<>(); private MutableExtensionRegistry(MutableExtensionRegistry parent) { this.parent = parent; } @Override public Stream stream(Class extensionType) { if (this.parent == null) { return streamLocal(extensionType); } return concat(this.parent.stream(extensionType), streamLocal(extensionType)); } /** * Stream all {@code Extensions} of the specified type that are present * in this registry. * *

Extensions in ancestors are ignored. * * @param extensionType the type of {@link Extension} to stream */ private Stream streamLocal(Class extensionType) { // @formatter:off return this.registeredExtensions.stream() .filter(extensionType::isInstance) .map(extensionType::cast); // @formatter:on } @Override public void registerExtension(Class extensionType) { if (!isAlreadyRegistered(extensionType)) { registerLocalExtension(ReflectionUtils.newInstance(extensionType)); } } /** * Determine if the supplied type is already registered in this registry or in a * parent registry. */ private boolean isAlreadyRegistered(Class extensionType) { return (this.registeredExtensionTypes.contains(extensionType) || (this.parent != null && this.parent.isAlreadyRegistered(extensionType))); } @Override public void registerExtension(Extension extension, Object source) { Preconditions.notNull(source, "source must not be null"); registerExtension("local", extension, source); } @Override public void registerSyntheticExtension(Extension extension, Object source) { registerExtension("synthetic", extension, source); } private void registerDefaultExtension(Extension extension) { registerExtension("default", extension); } private void registerAutoDetectedExtension(Extension extension) { registerExtension("auto-detected", extension); } private void registerLocalExtension(Extension extension) { registerExtension("local", extension); } private void registerExtension(String category, Extension extension) { registerExtension(category, extension, null); } private void registerExtension(String category, Extension extension, Object source) { Preconditions.notBlank(category, "category must not be null or blank"); Preconditions.notNull(extension, "Extension must not be null"); logger.trace( () -> String.format("Registering %s extension [%s]%s", category, extension, buildSourceInfo(source))); this.registeredExtensions.add(extension); this.registeredExtensionTypes.add(extension.getClass()); } private String buildSourceInfo(Object source) { if (source == null) { return ""; } if (source instanceof Member) { Member member = (Member) source; Object type = (member instanceof Method ? "method" : "field"); source = String.format("%s %s.%s", type, member.getDeclaringClass().getName(), member.getName()); } return " from source [" + source + "]"; } } RepeatedTestDisplayNameFormatter.java000066400000000000000000000024131455764576500400120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.RepeatedTest.CURRENT_REPETITION_PLACEHOLDER; import static org.junit.jupiter.api.RepeatedTest.DISPLAY_NAME_PLACEHOLDER; import static org.junit.jupiter.api.RepeatedTest.TOTAL_REPETITIONS_PLACEHOLDER; import org.junit.jupiter.api.RepeatedTest; /** * Display name formatter for a {@link RepeatedTest @RepeatedTest}. * * @since 5.0 */ class RepeatedTestDisplayNameFormatter { private final String pattern; private final String displayName; RepeatedTestDisplayNameFormatter(String pattern, String displayName) { this.pattern = pattern; this.displayName = displayName; } String format(int currentRepetition, int totalRepetitions) { return this.pattern// .replace(DISPLAY_NAME_PLACEHOLDER, this.displayName)// .replace(CURRENT_REPETITION_PLACEHOLDER, String.valueOf(currentRepetition))// .replace(TOTAL_REPETITIONS_PLACEHOLDER, String.valueOf(totalRepetitions)); } } RepeatedTestExtension.java000066400000000000000000000067101455764576500357000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; /** * {@code TestTemplateInvocationContextProvider} that supports the * {@link RepeatedTest @RepeatedTest} annotation. * * @since 5.0 */ class RepeatedTestExtension implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return isAnnotated(context.getTestMethod(), RepeatedTest.class); } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { Method testMethod = context.getRequiredTestMethod(); String displayName = context.getDisplayName(); RepeatedTest repeatedTest = AnnotationUtils.findAnnotation(testMethod, RepeatedTest.class).get(); int totalRepetitions = totalRepetitions(repeatedTest, testMethod); AtomicInteger failureCount = new AtomicInteger(); int failureThreshold = failureThreshold(repeatedTest, testMethod); RepeatedTestDisplayNameFormatter formatter = displayNameFormatter(repeatedTest, testMethod, displayName); // @formatter:off return IntStream .rangeClosed(1, totalRepetitions) .mapToObj(repetition -> new DefaultRepetitionInfo(repetition, totalRepetitions, failureCount, failureThreshold)) .map(repetitionInfo -> new RepeatedTestInvocationContext(repetitionInfo, formatter)); // @formatter:on } private int totalRepetitions(RepeatedTest repeatedTest, Method method) { int repetitions = repeatedTest.value(); Preconditions.condition(repetitions > 0, () -> String.format( "Configuration error: @RepeatedTest on method [%s] must be declared with a positive 'value'.", method)); return repetitions; } private int failureThreshold(RepeatedTest repeatedTest, Method method) { int failureThreshold = repeatedTest.failureThreshold(); if (failureThreshold != Integer.MAX_VALUE) { int repetitions = repeatedTest.value(); Preconditions.condition((failureThreshold > 0) && (failureThreshold < repetitions), () -> String.format("Configuration error: @RepeatedTest on method [%s] must declare a " + "'failureThreshold' greater than zero and less than the total number of repetitions [%d].", method, repetitions)); } return failureThreshold; } private RepeatedTestDisplayNameFormatter displayNameFormatter(RepeatedTest repeatedTest, Method method, String displayName) { String pattern = Preconditions.notBlank(repeatedTest.name().trim(), () -> String.format( "Configuration error: @RepeatedTest on method [%s] must be declared with a non-empty name.", method)); return new RepeatedTestDisplayNameFormatter(pattern, displayName); } } RepeatedTestInvocationContext.java000066400000000000000000000025641455764576500374050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Collections.singletonList; import java.util.List; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; /** * {@code TestTemplateInvocationContext} for a {@link org.junit.jupiter.api.RepeatedTest @RepeatedTest}. * * @since 5.0 */ class RepeatedTestInvocationContext implements TestTemplateInvocationContext { private final DefaultRepetitionInfo repetitionInfo; private final RepeatedTestDisplayNameFormatter formatter; public RepeatedTestInvocationContext(DefaultRepetitionInfo repetitionInfo, RepeatedTestDisplayNameFormatter formatter) { this.repetitionInfo = repetitionInfo; this.formatter = formatter; } @Override public String getDisplayName(int invocationIndex) { return this.formatter.format(this.repetitionInfo.currentRepetition, this.repetitionInfo.totalRepetitions); } @Override public List getAdditionalExtensions() { return singletonList(new RepetitionExtension(this.repetitionInfo)); } } RepetitionExtension.java000066400000000000000000000050741455764576500354330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.TestWatcher; /** * {@code RepetitionExtension} implements the following extension APIs to support * repetitions of a {@link RepeatedTest @RepeatedTest} method. * *

    *
  • {@link ParameterResolver} to resolve {@link RepetitionInfo} arguments
  • *
  • {@link TestWatcher} to track the {@linkplain RepetitionInfo#getFailureCount() * failure count}
  • *
  • {@link ExecutionCondition} to disable the repetition if the * {@linkplain RepetitionInfo#getFailureThreshold() failure threshold} has been * exceeded
  • *
* * @since 5.0 */ class RepetitionExtension implements ParameterResolver, TestWatcher, ExecutionCondition { private final DefaultRepetitionInfo repetitionInfo; RepetitionExtension(DefaultRepetitionInfo repetitionInfo) { this.repetitionInfo = repetitionInfo; } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return (parameterContext.getParameter().getType() == RepetitionInfo.class); } @Override public RepetitionInfo resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return this.repetitionInfo; } @Override public void testFailed(ExtensionContext context, Throwable cause) { this.repetitionInfo.failureCount.incrementAndGet(); } @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { int failureThreshold = this.repetitionInfo.failureThreshold; if (this.repetitionInfo.failureCount.get() >= failureThreshold) { return disabled("Failure threshold [" + failureThreshold + "] exceeded"); } return enabled("Failure threshold not exceeded"); } } SameThreadTimeoutInvocation.java000066400000000000000000000042441455764576500370300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.function.Supplier; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * @since 5.5 */ class SameThreadTimeoutInvocation implements Invocation { private final Invocation delegate; private final TimeoutDuration timeout; private final ScheduledExecutorService executor; private final Supplier descriptionSupplier; SameThreadTimeoutInvocation(Invocation delegate, TimeoutDuration timeout, ScheduledExecutorService executor, Supplier descriptionSupplier) { this.delegate = delegate; this.timeout = timeout; this.executor = executor; this.descriptionSupplier = descriptionSupplier; } @Override public T proceed() throws Throwable { InterruptTask interruptTask = new InterruptTask(Thread.currentThread()); ScheduledFuture future = executor.schedule(interruptTask, timeout.getValue(), timeout.getUnit()); Throwable failure = null; T result = null; try { result = delegate.proceed(); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); failure = t; } finally { boolean cancelled = future.cancel(false); if (!cancelled) { future.get(); } if (interruptTask.executed) { Thread.interrupted(); failure = TimeoutExceptionFactory.create(descriptionSupplier.get(), timeout, failure); } } if (failure != null) { throw failure; } return result; } static class InterruptTask implements Runnable { private final Thread thread; private volatile boolean executed; InterruptTask(Thread thread) { this.thread = thread; } @Override public void run() { executed = true; thread.interrupt(); } } } SeparateThreadTimeoutInvocation.java000066400000000000000000000025721455764576500377110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import java.util.concurrent.TimeoutException; import java.util.function.Supplier; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; /** * @since 5.9 */ class SeparateThreadTimeoutInvocation implements Invocation { private final Invocation delegate; private final TimeoutDuration timeout; private final Supplier descriptionSupplier; SeparateThreadTimeoutInvocation(Invocation delegate, TimeoutDuration timeout, Supplier descriptionSupplier) { this.delegate = delegate; this.timeout = timeout; this.descriptionSupplier = descriptionSupplier; } @Override public T proceed() throws Throwable { return assertTimeoutPreemptively(timeout.toDuration(), delegate::proceed, descriptionSupplier, (__, messageSupplier, cause) -> { TimeoutException exception = TimeoutExceptionFactory.create(messageSupplier.get(), timeout, null); exception.initCause(cause); return exception; }); } } TempDirectory.java000066400000000000000000000417731455764576500342140ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.nio.file.FileVisitResult.CONTINUE; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.api.io.CleanupMode.DEFAULT; import static org.junit.jupiter.api.io.CleanupMode.NEVER; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.ReflectionUtils.makeAccessible; import java.io.File; import java.io.IOException; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Parameter; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributeView; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.function.Predicate; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.config.EnumConfigurationParameterConverter; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code TempDirectory} is a JUnit Jupiter extension that creates and cleans * up temporary directories if field in a test class or a parameter in a * lifecycle method or test method is annotated with {@code @TempDir}. * *

Consult the Javadoc for {@link TempDir} for details on the contract. * * @since 5.4 * @see TempDir * @see Files#createTempDirectory */ class TempDirectory implements BeforeAllCallback, BeforeEachCallback, ParameterResolver { static final Namespace NAMESPACE = Namespace.create(TempDirectory.class); private static final String KEY = "temp.dir"; private static final String FAILURE_TRACKER = "failure.tracker"; private static final String CHILD_FAILED = "child.failed"; // for testing purposes static final String FILE_OPERATIONS_KEY = "file.operations"; private final JupiterConfiguration configuration; public TempDirectory(JupiterConfiguration configuration) { this.configuration = configuration; } /** * Perform field injection for non-private, {@code static} fields (i.e., * class fields) of type {@link Path} or {@link File} that are annotated with * {@link TempDir @TempDir}. */ @Override public void beforeAll(ExtensionContext context) { installFailureTracker(context); injectStaticFields(context, context.getRequiredTestClass()); } /** * Perform field injection for non-private, non-static fields (i.e., * instance fields) of type {@link Path} or {@link File} that are annotated * with {@link TempDir @TempDir}. */ @Override public void beforeEach(ExtensionContext context) { installFailureTracker(context); context.getRequiredTestInstances().getAllInstances() // .forEach(instance -> injectInstanceFields(context, instance)); } private static void installFailureTracker(ExtensionContext context) { context.getStore(NAMESPACE).put(FAILURE_TRACKER, (CloseableResource) () -> context.getParent() // .ifPresent(it -> { if (selfOrChildFailed(context)) { it.getStore(NAMESPACE).put(CHILD_FAILED, true); } })); } private void injectStaticFields(ExtensionContext context, Class testClass) { injectFields(context, null, testClass, ReflectionUtils::isStatic); } private void injectInstanceFields(ExtensionContext context, Object instance) { injectFields(context, instance, instance.getClass(), ReflectionUtils::isNotStatic); } private void injectFields(ExtensionContext context, Object testInstance, Class testClass, Predicate predicate) { Scope scope = getScope(context); findAnnotatedFields(testClass, TempDir.class, predicate).forEach(field -> { assertNonFinalField(field); assertSupportedType("field", field.getType()); try { CleanupMode cleanupMode = determineCleanupModeForField(field); TempDirFactory factory = determineTempDirFactoryForField(field, scope); makeAccessible(field).set(testInstance, getPathOrFile(new FieldContext(field), field.getType(), factory, cleanupMode, scope, context)); } catch (Throwable t) { ExceptionUtils.throwAsUncheckedException(t); } }); } /** * Determine if the {@link Parameter} in the supplied {@link ParameterContext} * is annotated with {@link TempDir @TempDir}. */ @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { boolean annotated = parameterContext.isAnnotated(TempDir.class); if (annotated && parameterContext.getDeclaringExecutable() instanceof Constructor) { throw new ParameterResolutionException( "@TempDir is not supported on constructor parameters. Please use field injection instead."); } return annotated; } /** * Resolve the current temporary directory for the {@link Parameter} in the * supplied {@link ParameterContext}. */ @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Class parameterType = parameterContext.getParameter().getType(); assertSupportedType("parameter", parameterType); CleanupMode cleanupMode = determineCleanupModeForParameter(parameterContext); Scope scope = getScope(extensionContext); TempDirFactory factory = determineTempDirFactoryForParameter(parameterContext, scope); return getPathOrFile(parameterContext, parameterType, factory, cleanupMode, scope, extensionContext); } private CleanupMode determineCleanupModeForField(Field field) { TempDir tempDir = findAnnotation(field, TempDir.class).orElseThrow( () -> new JUnitException("Field " + field + " must be annotated with @TempDir")); return determineCleanupMode(tempDir); } private CleanupMode determineCleanupModeForParameter(ParameterContext parameterContext) { TempDir tempDir = parameterContext.findAnnotation(TempDir.class).orElseThrow(() -> new JUnitException( "Parameter " + parameterContext.getParameter() + " must be annotated with @TempDir")); return determineCleanupMode(tempDir); } private CleanupMode determineCleanupMode(TempDir tempDir) { CleanupMode cleanupMode = tempDir.cleanup(); return cleanupMode == DEFAULT ? this.configuration.getDefaultTempDirCleanupMode() : cleanupMode; } @SuppressWarnings("deprecation") private Scope getScope(ExtensionContext context) { return context.getRoot().getStore(NAMESPACE).getOrComputeIfAbsent( // Scope.class, // __ -> new EnumConfigurationParameterConverter<>(Scope.class, "@TempDir scope") // .get(TempDir.SCOPE_PROPERTY_NAME, context::getConfigurationParameter, Scope.PER_DECLARATION), // Scope.class // ); } private TempDirFactory determineTempDirFactoryForField(Field field, Scope scope) { TempDir tempDir = findAnnotation(field, TempDir.class).orElseThrow( () -> new JUnitException("Field " + field + " must be annotated with @TempDir")); return determineTempDirFactory(tempDir, scope); } private TempDirFactory determineTempDirFactoryForParameter(ParameterContext parameterContext, Scope scope) { TempDir tempDir = parameterContext.findAnnotation(TempDir.class).orElseThrow(() -> new JUnitException( "Parameter " + parameterContext.getParameter() + " must be annotated with @TempDir")); return determineTempDirFactory(tempDir, scope); } @SuppressWarnings("deprecation") private TempDirFactory determineTempDirFactory(TempDir tempDir, Scope scope) { Class factory = tempDir.factory(); if (factory != TempDirFactory.class && scope == Scope.PER_CONTEXT) { throw new ExtensionConfigurationException("Custom @TempDir factory is not supported with " + TempDir.SCOPE_PROPERTY_NAME + "=" + Scope.PER_CONTEXT.name().toLowerCase() + ". Use " + TempDir.DEFAULT_FACTORY_PROPERTY_NAME + " instead."); } return factory == TempDirFactory.class // ? this.configuration.getDefaultTempDirFactorySupplier().get() : ReflectionUtils.newInstance(factory); } private void assertNonFinalField(Field field) { if (ReflectionUtils.isFinal(field)) { throw new ExtensionConfigurationException("@TempDir field [" + field + "] must not be declared as final."); } } private void assertSupportedType(String target, Class type) { if (type != Path.class && type != File.class) { throw new ExtensionConfigurationException("Can only resolve @TempDir " + target + " of type " + Path.class.getName() + " or " + File.class.getName() + " but was: " + type.getName()); } } private Object getPathOrFile(AnnotatedElementContext elementContext, Class type, TempDirFactory factory, CleanupMode cleanupMode, Scope scope, ExtensionContext extensionContext) { Namespace namespace = scope == Scope.PER_DECLARATION // ? NAMESPACE.append(elementContext) // : NAMESPACE; Path path = extensionContext.getStore(namespace) // .getOrComputeIfAbsent(KEY, __ -> createTempDir(factory, cleanupMode, elementContext, extensionContext), CloseablePath.class) // .get(); return (type == Path.class) ? path : path.toFile(); } static CloseablePath createTempDir(TempDirFactory factory, CleanupMode cleanupMode, AnnotatedElementContext elementContext, ExtensionContext extensionContext) { try { return new CloseablePath(factory, cleanupMode, elementContext, extensionContext); } catch (Exception ex) { throw new ExtensionConfigurationException("Failed to create default temp directory", ex); } } private static boolean selfOrChildFailed(ExtensionContext context) { return context.getExecutionException().isPresent() // || context.getStore(NAMESPACE).getOrDefault(CHILD_FAILED, Boolean.class, false); } static class CloseablePath implements CloseableResource { private static final Logger logger = LoggerFactory.getLogger(CloseablePath.class); private final Path dir; private final TempDirFactory factory; private final CleanupMode cleanupMode; private final ExtensionContext extensionContext; CloseablePath(TempDirFactory factory, CleanupMode cleanupMode, AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { this.dir = factory.createTempDirectory(elementContext, extensionContext); this.factory = factory; this.cleanupMode = cleanupMode; this.extensionContext = extensionContext; } Path get() { return dir; } @Override public void close() throws IOException { try { if (cleanupMode == NEVER || (cleanupMode == ON_SUCCESS && selfOrChildFailed(extensionContext))) { logger.info(() -> "Skipping cleanup of temp dir " + dir + " due to cleanup mode configuration."); return; } FileOperations fileOperations = extensionContext.getStore(NAMESPACE) // .getOrDefault(FILE_OPERATIONS_KEY, FileOperations.class, FileOperations.DEFAULT); SortedMap failures = deleteAllFilesAndDirectories(fileOperations); if (!failures.isEmpty()) { throw createIOExceptionWithAttachedFailures(failures); } } finally { factory.close(); } } private SortedMap deleteAllFilesAndDirectories(FileOperations fileOperations) throws IOException { if (Files.notExists(dir)) { return Collections.emptySortedMap(); } SortedMap failures = new TreeMap<>(); Set retriedPaths = new HashSet<>(); tryToResetPermissions(dir); Files.walkFileTree(dir, new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { if (!dir.equals(CloseablePath.this.dir)) { tryToResetPermissions(dir); } return CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { // IOException includes `AccessDeniedException` thrown by non-readable or non-executable flags resetPermissionsAndTryToDeleteAgain(file, exc); return CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { return deleteAndContinue(file); } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { return deleteAndContinue(dir); } private FileVisitResult deleteAndContinue(Path path) { try { fileOperations.delete(path); } catch (NoSuchFileException ignore) { // ignore } catch (DirectoryNotEmptyException exception) { failures.put(path, exception); } catch (IOException exception) { // IOException includes `AccessDeniedException` thrown by non-readable or non-executable flags resetPermissionsAndTryToDeleteAgain(path, exception); } return CONTINUE; } private void resetPermissionsAndTryToDeleteAgain(Path path, IOException exception) { boolean notYetRetried = retriedPaths.add(path); if (notYetRetried) { try { tryToResetPermissions(path); if (Files.isDirectory(path)) { Files.walkFileTree(path, this); } else { fileOperations.delete(path); } } catch (Exception suppressed) { exception.addSuppressed(suppressed); failures.put(path, exception); } } else { failures.put(path, exception); } } }); return failures; } @SuppressWarnings("ResultOfMethodCallIgnored") private static void tryToResetPermissions(Path path) { File file; try { file = path.toFile(); } catch (UnsupportedOperationException ignore) { // Might happen when the `TempDirFactory` uses a custom `FileSystem` return; } file.setReadable(true); file.setWritable(true); if (Files.isDirectory(path)) { file.setExecutable(true); } DosFileAttributeView dos = Files.getFileAttributeView(path, DosFileAttributeView.class); if (dos != null) { try { dos.setReadOnly(false); } catch (IOException ignore) { // nothing we can do } } } private IOException createIOExceptionWithAttachedFailures(SortedMap failures) { Path emptyPath = Paths.get(""); String joinedPaths = failures.keySet().stream() // .map(this::tryToDeleteOnExit) // .map(this::relativizeSafely) // .map(path -> emptyPath.equals(path) ? "" : path.toString()) // .collect(joining(", ")); IOException exception = new IOException("Failed to delete temp directory " + dir.toAbsolutePath() + ". The following paths could not be deleted (see suppressed exceptions for details): " + joinedPaths); failures.values().forEach(exception::addSuppressed); return exception; } private Path tryToDeleteOnExit(Path path) { try { path.toFile().deleteOnExit(); } catch (UnsupportedOperationException ignore) { } return path; } private Path relativizeSafely(Path path) { try { return dir.relativize(path); } catch (IllegalArgumentException e) { return path; } } } enum Scope { PER_CONTEXT, PER_DECLARATION } interface FileOperations { FileOperations DEFAULT = Files::delete; void delete(Path path) throws IOException; } private static class FieldContext implements AnnotatedElementContext { private final Field field; private FieldContext(Field field) { this.field = Preconditions.notNull(field, "field must not be null"); } @Override public AnnotatedElement getAnnotatedElement() { return this.field; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("field", this.field) .toString(); // @formatter:on } } } TestInfoParameterResolver.java000066400000000000000000000047561455764576500365400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.lang.reflect.Method; import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.util.ToStringBuilder; /** * {@link ParameterResolver} that resolves the {@link TestInfo} for * the currently executing test. * * @since 5.0 */ class TestInfoParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return (parameterContext.getParameter().getType() == TestInfo.class); } @Override public TestInfo resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return new DefaultTestInfo(extensionContext); } private static class DefaultTestInfo implements TestInfo { private final String displayName; private final Set tags; private final Optional> testClass; private final Optional testMethod; DefaultTestInfo(ExtensionContext extensionContext) { this.displayName = extensionContext.getDisplayName(); this.tags = extensionContext.getTags(); this.testClass = extensionContext.getTestClass(); this.testMethod = extensionContext.getTestMethod(); } @Override public String getDisplayName() { return this.displayName; } @Override public Set getTags() { return this.tags; } @Override public Optional> getTestClass() { return this.testClass; } @Override public Optional getTestMethod() { return this.testMethod; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("displayName", this.displayName) .append("tags", this.tags) .append("testClass", nullSafeGet(this.testClass)) .append("testMethod", nullSafeGet(this.testMethod)) .toString(); // @formatter:on } private static Object nullSafeGet(Optional optional) { return optional != null ? optional.orElse(null) : null; } } } TestReporterParameterResolver.java000066400000000000000000000021221455764576500374300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * {@link ParameterResolver} that injects a {@link TestReporter}. * * @since 5.0 */ class TestReporterParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return (parameterContext.getParameter().getType() == TestReporter.class); } @Override public TestReporter resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return extensionContext::publishReportEntry; } } TimeoutConfiguration.java000066400000000000000000000136541455764576500355750ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Timeout.DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.ThreadMode.SAME_THREAD; import static org.junit.jupiter.api.Timeout.ThreadMode.SEPARATE_THREAD; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * @since 5.5 */ class TimeoutConfiguration { private static final Logger logger = LoggerFactory.getLogger(TimeoutConfiguration.class); private final TimeoutDurationParser parser = new TimeoutDurationParser(); private final Map> cache = new ConcurrentHashMap<>(); private final AtomicReference> threadMode = new AtomicReference<>(); private final ExtensionContext extensionContext; TimeoutConfiguration(ExtensionContext extensionContext) { this.extensionContext = extensionContext; } Optional getDefaultTestMethodTimeout() { return parseOrDefault(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultTestableMethodTimeout); } Optional getDefaultTestTemplateMethodTimeout() { return parseOrDefault(DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultTestableMethodTimeout); } Optional getDefaultTestFactoryMethodTimeout() { return parseOrDefault(DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultTestableMethodTimeout); } Optional getDefaultBeforeAllMethodTimeout() { return parseOrDefault(DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultLifecycleMethodTimeout); } Optional getDefaultBeforeEachMethodTimeout() { return parseOrDefault(DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultLifecycleMethodTimeout); } Optional getDefaultAfterEachMethodTimeout() { return parseOrDefault(DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultLifecycleMethodTimeout); } Optional getDefaultAfterAllMethodTimeout() { return parseOrDefault(DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultLifecycleMethodTimeout); } private Optional getDefaultTestableMethodTimeout() { return parseOrDefault(DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultTimeout); } private Optional getDefaultLifecycleMethodTimeout() { return parseOrDefault(DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME, this::getDefaultTimeout); } private Optional getDefaultTimeout() { return parseTimeoutDuration(DEFAULT_TIMEOUT_PROPERTY_NAME); } private Optional parseOrDefault(String propertyName, Supplier> defaultSupplier) { Optional timeoutConfiguration = parseTimeoutDuration(propertyName); return timeoutConfiguration.isPresent() ? timeoutConfiguration : defaultSupplier.get(); } private Optional parseTimeoutDuration(String propertyName) { return cache.computeIfAbsent(propertyName, key -> extensionContext.getConfigurationParameter(key).map(value -> { try { return parser.parse(value); } catch (Exception e) { logger.warn(e, () -> String.format("Ignored invalid timeout '%s' set via the '%s' configuration parameter.", value, key)); return null; } })); } Optional getDefaultTimeoutThreadMode() { if (threadMode.get() != null) { return threadMode.get(); } else { Optional configuredThreadMode = parseTimeoutThreadModeConfiguration(); threadMode.set(configuredThreadMode); return configuredThreadMode; } } private Optional parseTimeoutThreadModeConfiguration() { return extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME).map(value -> { try { ThreadMode threadMode = ThreadMode.valueOf(value.toUpperCase()); if (threadMode == ThreadMode.INFERRED) { logger.warn(() -> String.format( "Invalid timeout thread mode '%s', only %s and %s can be used as configuration parameter for %s.", value, SAME_THREAD, SEPARATE_THREAD, DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); return null; } return threadMode; } catch (Exception e) { logger.warn(e, () -> String.format("Invalid timeout thread mode '%s' set via the '%s' configuration parameter.", value, DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); return null; } }); } } TimeoutDuration.java000066400000000000000000000044161455764576500345470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Objects; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Timeout; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; /** * @since 5.5 */ class TimeoutDuration { static TimeoutDuration from(Timeout timeout) { return new TimeoutDuration(timeout.value(), timeout.unit()); } private final long value; private final TimeUnit unit; TimeoutDuration(long value, TimeUnit unit) { Preconditions.condition(value > 0, () -> "timeout duration must be a positive number: " + value); this.value = value; this.unit = Preconditions.notNull(unit, "timeout unit must not be null"); } public long getValue() { return value; } public TimeUnit getUnit() { return unit; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } TimeoutDuration that = (TimeoutDuration) o; return value == that.value && unit == that.unit; } @Override public int hashCode() { return Objects.hash(value, unit); } @Override public String toString() { String label = unit.name().toLowerCase(); if (value == 1 && label.endsWith("s")) { label = label.substring(0, label.length() - 1); } return value + " " + label; } public Duration toDuration() { return Duration.of(value, toChronoUnit()); } private ChronoUnit toChronoUnit() { switch (unit) { case NANOSECONDS: return ChronoUnit.NANOS; case MICROSECONDS: return ChronoUnit.MICROS; case MILLISECONDS: return ChronoUnit.MILLIS; case SECONDS: return ChronoUnit.SECONDS; case MINUTES: return ChronoUnit.MINUTES; case HOURS: return ChronoUnit.HOURS; case DAYS: return ChronoUnit.DAYS; default: throw new JUnitException("Could not map TimeUnit " + unit + " to ChronoUnit"); } } } TimeoutDurationParser.java000066400000000000000000000044751455764576500357310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.regex.Pattern.CASE_INSENSITIVE; import static java.util.regex.Pattern.UNICODE_CASE; import java.time.format.DateTimeParseException; import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @since 5.5 */ class TimeoutDurationParser { private static final Pattern PATTERN = Pattern.compile("([1-9]\\d*) ?((?:[nμm]?s)|m|h|d)?", CASE_INSENSITIVE | UNICODE_CASE); private static final Map UNITS_BY_ABBREVIATION; static { Map unitsByAbbreviation = new HashMap<>(); unitsByAbbreviation.put("ns", NANOSECONDS); unitsByAbbreviation.put("μs", MICROSECONDS); unitsByAbbreviation.put("ms", MILLISECONDS); unitsByAbbreviation.put("s", SECONDS); unitsByAbbreviation.put("m", MINUTES); unitsByAbbreviation.put("h", HOURS); unitsByAbbreviation.put("d", DAYS); UNITS_BY_ABBREVIATION = Collections.unmodifiableMap(unitsByAbbreviation); } TimeoutDuration parse(CharSequence text) throws DateTimeParseException { Matcher matcher = PATTERN.matcher(text); if (matcher.matches()) { long value = Long.parseLong(matcher.group(1)); String unitAbbreviation = matcher.group(2); TimeUnit unit = unitAbbreviation == null ? SECONDS : UNITS_BY_ABBREVIATION.get(unitAbbreviation.toLowerCase(Locale.ENGLISH)); return new TimeoutDuration(value, unit); } throw new DateTimeParseException("Timeout duration is not in the expected format ( [ns|μs|ms|s|m|h|d])", text, 0); } } TimeoutExceptionFactory.java000066400000000000000000000022751455764576500362510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.util.concurrent.TimeoutException; import org.junit.platform.commons.util.Preconditions; /** * @since 5.9 */ class TimeoutExceptionFactory { private TimeoutExceptionFactory() { } static TimeoutException create(String methodSignature, TimeoutDuration timeoutDuration, Throwable failure) { String message = String.format("%s timed out after %s", Preconditions.notNull(methodSignature, "method signature must not be null"), Preconditions.notNull(timeoutDuration, "timeout duration must not be null")); TimeoutException timeoutException = new TimeoutException(message); if (failure != null) { timeoutException.addSuppressed(failure); } return timeoutException; } static TimeoutException create(String methodSignature, TimeoutDuration timeoutDuration) { return create(methodSignature, timeoutDuration, null); } } TimeoutExtension.java000066400000000000000000000236131455764576500347360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Timeout.TIMEOUT_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.ThreadMode.SAME_THREAD; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import java.util.function.Function; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.jupiter.engine.extension.TimeoutInvocationFactory.TimeoutInvocationParameters; import org.junit.platform.commons.support.AnnotationSupport; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.RuntimeUtils; /** * @since 5.5 */ class TimeoutExtension implements BeforeAllCallback, BeforeEachCallback, InvocationInterceptor { private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(Timeout.class); private static final String TESTABLE_METHOD_TIMEOUT_KEY = "testable_method_timeout_from_annotation"; private static final String TESTABLE_METHOD_TIMEOUT_THREAD_MODE_KEY = "testable_method_timeout_thread_mode_from_annotation"; private static final String GLOBAL_TIMEOUT_CONFIG_KEY = "global_timeout_config"; private static final String ENABLED_MODE_VALUE = "enabled"; private static final String DISABLED_MODE_VALUE = "disabled"; private static final String DISABLED_ON_DEBUG_MODE_VALUE = "disabled_on_debug"; @Override public void beforeAll(ExtensionContext context) { readAndStoreTimeoutSoChildrenInheritIt(context); } @Override public void beforeEach(ExtensionContext context) { readAndStoreTimeoutSoChildrenInheritIt(context); } private void readAndStoreTimeoutSoChildrenInheritIt(ExtensionContext context) { readTimeoutFromAnnotation(context.getElement()).ifPresent( timeout -> context.getStore(NAMESPACE).put(TESTABLE_METHOD_TIMEOUT_KEY, timeout)); readTimeoutThreadModeFromAnnotation(context.getElement()).ifPresent( timeoutThreadMode -> context.getStore(NAMESPACE).put(TESTABLE_METHOD_TIMEOUT_THREAD_MODE_KEY, timeoutThreadMode)); } @Override public void interceptBeforeAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultBeforeAllMethodTimeout); } @Override public void interceptBeforeEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultBeforeEachMethodTimeout); } @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestMethodTimeout); } @Override public void interceptTestTemplateMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestTemplateMethodTimeout); } @Override public T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { return interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestFactoryMethodTimeout); } @Override public void interceptAfterEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultAfterEachMethodTimeout); } @Override public void interceptAfterAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultAfterAllMethodTimeout); } private void interceptLifecycleMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = readTimeoutFromAnnotation(Optional.of(invocationContext.getExecutable())).orElse( null); intercept(invocation, invocationContext, extensionContext, timeout, defaultTimeoutProvider); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private Optional readTimeoutFromAnnotation(Optional element) { return AnnotationSupport.findAnnotation(element, Timeout.class).map(TimeoutDuration::from); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private Optional readTimeoutThreadModeFromAnnotation(Optional element) { return AnnotationSupport.findAnnotation(element, Timeout.class).map(Timeout::threadMode); } private T interceptTestableMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = extensionContext.getStore(NAMESPACE).get(TESTABLE_METHOD_TIMEOUT_KEY, TimeoutDuration.class); return intercept(invocation, invocationContext, extensionContext, timeout, defaultTimeoutProvider); } private T intercept(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutDuration explicitTimeout, TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = explicitTimeout == null ? getDefaultTimeout(extensionContext, defaultTimeoutProvider) : explicitTimeout; return decorate(invocation, invocationContext, extensionContext, timeout).proceed(); } private TimeoutDuration getDefaultTimeout(ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) { return defaultTimeoutProvider.apply(getGlobalTimeoutConfiguration(extensionContext)).orElse(null); } private TimeoutConfiguration getGlobalTimeoutConfiguration(ExtensionContext extensionContext) { ExtensionContext root = extensionContext.getRoot(); return root.getStore(NAMESPACE).getOrComputeIfAbsent(GLOBAL_TIMEOUT_CONFIG_KEY, key -> new TimeoutConfiguration(root), TimeoutConfiguration.class); } private Invocation decorate(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutDuration timeout) { if (timeout == null || isTimeoutDisabled(extensionContext)) { return invocation; } ThreadMode threadMode = resolveTimeoutThreadMode(extensionContext); return new TimeoutInvocationFactory(extensionContext.getRoot().getStore(NAMESPACE)).create(threadMode, new TimeoutInvocationParameters<>(invocation, timeout, () -> describe(invocationContext, extensionContext))); } private ThreadMode resolveTimeoutThreadMode(ExtensionContext extensionContext) { ThreadMode annotationThreadMode = getAnnotationThreadMode(extensionContext); if (annotationThreadMode == null || annotationThreadMode == ThreadMode.INFERRED) { return getGlobalTimeoutConfiguration(extensionContext).getDefaultTimeoutThreadMode().orElse(SAME_THREAD); } return annotationThreadMode; } private ThreadMode getAnnotationThreadMode(ExtensionContext extensionContext) { return extensionContext.getStore(NAMESPACE).get(TESTABLE_METHOD_TIMEOUT_THREAD_MODE_KEY, ThreadMode.class); } private String describe(ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) { Method method = invocationContext.getExecutable(); Optional> testClass = extensionContext.getTestClass(); if (testClass.isPresent() && invocationContext.getTargetClass().equals(testClass.get())) { return String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); } return ReflectionUtils.getFullyQualifiedMethodName(invocationContext.getTargetClass(), method); } /** * Determine if timeouts are disabled for the supplied extension context. */ private boolean isTimeoutDisabled(ExtensionContext extensionContext) { Optional mode = extensionContext.getConfigurationParameter(TIMEOUT_MODE_PROPERTY_NAME); return mode.map(this::isTimeoutDisabled).orElse(false); } /** * Determine if timeouts are disabled for the supplied mode. */ private boolean isTimeoutDisabled(String mode) { switch (mode) { case ENABLED_MODE_VALUE: return false; case DISABLED_MODE_VALUE: return true; case DISABLED_ON_DEBUG_MODE_VALUE: return RuntimeUtils.isDebugMode(); default: throw new ExtensionConfigurationException("Unsupported timeout mode: " + mode); } } @FunctionalInterface private interface TimeoutProvider extends Function> { } } TimeoutInvocationFactory.java000066400000000000000000000075271455764576500364310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; /** * @since 5.9 */ class TimeoutInvocationFactory { private final Store store; TimeoutInvocationFactory(Store store) { this.store = Preconditions.notNull(store, "store must not be null"); } Invocation create(ThreadMode threadMode, TimeoutInvocationParameters timeoutInvocationParameters) { Preconditions.notNull(threadMode, "thread mode must not be null"); Preconditions.condition(threadMode != ThreadMode.INFERRED, "thread mode must not be INFERRED"); Preconditions.notNull(timeoutInvocationParameters, "timeout invocation parameters must not be null"); if (threadMode == ThreadMode.SEPARATE_THREAD) { return new SeparateThreadTimeoutInvocation<>(timeoutInvocationParameters.getInvocation(), timeoutInvocationParameters.getTimeoutDuration(), timeoutInvocationParameters.getDescriptionSupplier()); } return new SameThreadTimeoutInvocation<>(timeoutInvocationParameters.getInvocation(), timeoutInvocationParameters.getTimeoutDuration(), getThreadExecutorForSameThreadInvocation(), timeoutInvocationParameters.getDescriptionSupplier()); } private ScheduledExecutorService getThreadExecutorForSameThreadInvocation() { return store.getOrComputeIfAbsent(SingleThreadExecutorResource.class).get(); } private static abstract class ExecutorResource implements CloseableResource { protected final ScheduledExecutorService executor; ExecutorResource(ScheduledExecutorService executor) { this.executor = executor; } ScheduledExecutorService get() { return executor; } @Override public void close() throws Throwable { executor.shutdown(); boolean terminated = executor.awaitTermination(5, TimeUnit.SECONDS); if (!terminated) { executor.shutdownNow(); throw new JUnitException("Scheduled executor could not be stopped in an orderly manner"); } } } static class SingleThreadExecutorResource extends ExecutorResource { @SuppressWarnings("unused") SingleThreadExecutorResource() { super(Executors.newSingleThreadScheduledExecutor(runnable -> { Thread thread = new Thread(runnable, "junit-jupiter-timeout-watcher"); thread.setPriority(Thread.MAX_PRIORITY); return thread; })); } } static class TimeoutInvocationParameters { private final Invocation invocation; private final TimeoutDuration timeout; private final Supplier descriptionSupplier; TimeoutInvocationParameters(Invocation invocation, TimeoutDuration timeout, Supplier descriptionSupplier) { this.invocation = Preconditions.notNull(invocation, "invocation must not be null"); this.timeout = Preconditions.notNull(timeout, "timeout must not be null"); this.descriptionSupplier = Preconditions.notNull(descriptionSupplier, "description supplier must not be null"); } public Invocation getInvocation() { return invocation; } public TimeoutDuration getTimeoutDuration() { return timeout; } public Supplier getDescriptionSupplier() { return descriptionSupplier; } } } package-info.java000066400000000000000000000001631455764576500337320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/** * Test extensions specific to the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.extension; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/package-info.java000066400000000000000000000001361455764576500317750ustar00rootroot00000000000000/** * Core package for the JUnit Jupiter test engine. */ package org.junit.jupiter.engine; junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/000077500000000000000000000000001455764576500303225ustar00rootroot00000000000000JupiterThrowableCollectorFactory.java000066400000000000000000000021441455764576500376000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.support; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * Factory for creating {@link ThrowableCollector ThrowableCollectors} within * the JUnit Jupiter test engine. * * @since 5.4 * @see ThrowableCollector */ @API(status = INTERNAL, since = "5.4") public class JupiterThrowableCollectorFactory { /** * Create a new {@link ThrowableCollector} that treats instances of the * OTA's {@link org.opentest4j.TestAbortedException} and JUnit 4's * {@code org.junit.AssumptionViolatedException} as aborting. */ public static ThrowableCollector createThrowableCollector() { return new OpenTest4JAndJUnit4AwareThrowableCollector(); } } OpenTest4JAndJUnit4AwareThrowableCollector.java000066400000000000000000000052431455764576500412310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.support; import java.util.function.Predicate; import java.util.function.Supplier; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; import org.opentest4j.TestAbortedException; /** * Specialization of {@link ThrowableCollector} that treats instances of the * OTA's {@link org.opentest4j.TestAbortedException} and JUnit 4's * {@code org.junit.AssumptionViolatedException} as aborting. * * @since 5.4 * @see ThrowableCollector * @see org.junit.platform.engine.support.hierarchical.OpenTest4JAwareThrowableCollector */ class OpenTest4JAndJUnit4AwareThrowableCollector extends ThrowableCollector { private static final Logger logger = LoggerFactory.getLogger(OpenTest4JAndJUnit4AwareThrowableCollector.class); private static final String ASSUMPTION_VIOLATED_EXCEPTION = "org.junit.internal.AssumptionViolatedException"; private static final String COMMON_FAILURE_MESSAGE = "Failed to load class " + ASSUMPTION_VIOLATED_EXCEPTION + ": only supporting " + TestAbortedException.class.getName() + " for aborted execution."; private static final Predicate abortedExecutionPredicate = createAbortedExecutionPredicate(); OpenTest4JAndJUnit4AwareThrowableCollector() { super(abortedExecutionPredicate); } private static Predicate createAbortedExecutionPredicate() { Predicate otaPredicate = TestAbortedException.class::isInstance; // Additionally support JUnit 4's AssumptionViolatedException? try { Class clazz = ReflectionUtils.tryToLoadClass(ASSUMPTION_VIOLATED_EXCEPTION).get(); if (clazz != null) { return otaPredicate.or(clazz::isInstance); } } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); Supplier messageSupplier = (throwable instanceof NoClassDefFoundError) ? () -> COMMON_FAILURE_MESSAGE + " Note that " + ASSUMPTION_VIOLATED_EXCEPTION + " requires that Hamcrest is on the classpath." : () -> COMMON_FAILURE_MESSAGE; logger.debug(throwable, messageSupplier); } // Else just OTA's TestAbortedException return otaPredicate; } } junit5-r5.10.2/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/package-info.java000066400000000000000000000001621455764576500335100ustar00rootroot00000000000000/** * Internal support classes for the JUnit Jupiter test engine. */ package org.junit.jupiter.engine.support; junit5-r5.10.2/junit-jupiter-engine/src/main/resources/000077500000000000000000000000001455764576500230305ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/resources/META-INF/000077500000000000000000000000001455764576500241705ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500260135ustar00rootroot00000000000000org.junit.platform.engine.TestEngine000066400000000000000000000000521455764576500347260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/main/resources/META-INF/servicesorg.junit.jupiter.engine.JupiterTestEnginejunit5-r5.10.2/junit-jupiter-engine/src/module/000077500000000000000000000000001455764576500213575ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/module/org.junit.jupiter.engine/000077500000000000000000000000001455764576500262235ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java000066400000000000000000000021201455764576500312770ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Provides the JUnit Jupiter {@linkplain org.junit.platform.engine.TestEngine} * implementation. * * @since 5.0 * @uses org.junit.jupiter.api.extension.Extension * @provides org.junit.platform.engine.TestEngine The {@code JupiterTestEngine} * runs Jupiter based tests on the platform. */ module org.junit.jupiter.engine { requires static org.apiguardian.api; requires org.junit.jupiter.api; requires org.junit.platform.commons; requires org.junit.platform.engine; requires org.opentest4j; // exports org.junit.jupiter.engine; // Constants... uses org.junit.jupiter.api.extension.Extension; provides org.junit.platform.engine.TestEngine with org.junit.jupiter.engine.JupiterTestEngine; opens org.junit.jupiter.engine.extension to org.junit.platform.commons; } junit5-r5.10.2/junit-jupiter-engine/src/test/000077500000000000000000000000001455764576500210515ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/000077500000000000000000000000001455764576500223765ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/000077500000000000000000000000001455764576500231655ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/000077500000000000000000000000001455764576500243165ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/jupiter/000077500000000000000000000000001455764576500260005ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/jupiter/api/000077500000000000000000000000001455764576500265515ustar00rootroot00000000000000GroovyAssertEqualsTests.groovy000066400000000000000000000134611455764576500346130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/jupiter/api/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api import java.util.function.Supplier import static org.junit.jupiter.api.Assertions.assertEquals import static org.junit.jupiter.api.PrimitiveAndWrapperTypeHelpers.* class GroovyAssertEqualsTests { Supplier supplier = { '' } @Test void "null references can be passed to assertEquals"() { Object null1 = null Object null2 = null assertEquals(null1, null) assertEquals(null, null2) assertEquals(null1, null2) } @Test void "integers can be passed to assertEquals"() { assertEquals(i(42), i(42)) assertEquals(i(42), I(42)) assertEquals(I(42), i(42)) assertEquals(I(42), I(42)) assertEquals(i(42), i(42), '') assertEquals(i(42), I(42), '') assertEquals(I(42), i(42), '') assertEquals(I(42), I(42), '') assertEquals(i(42), i(42), supplier) assertEquals(i(42), I(42), supplier) assertEquals(I(42), i(42), supplier) assertEquals(I(42), I(42), supplier) } @Test void "floats can be passed to assertEquals"() { assertEquals(f(42), f(42)) assertEquals(f(42), F(42)) assertEquals(F(42), f(42)) assertEquals(F(42), F(42)) assertEquals(f(42), f(42), '') assertEquals(f(42), F(42), '') assertEquals(F(42), f(42), '') assertEquals(F(42), F(42), '') assertEquals(f(42), f(42), supplier) assertEquals(f(42), F(42), supplier) assertEquals(F(42), f(42), supplier) assertEquals(F(42), F(42), supplier) } @Test void "floats can be passed to assertEquals with delta"() { assertEquals(f(42), f(42), 0.01f) assertEquals(f(42), F(42), 0.01f) assertEquals(F(42), f(42), 0.01f) assertEquals(F(42), F(42), 0.01f) assertEquals(f(42), f(42), 0.01f, '') assertEquals(f(42), F(42), 0.01f, '') assertEquals(F(42), f(42), 0.01f, '') assertEquals(F(42), F(42), 0.01f, '') assertEquals(f(42), f(42), 0.01f, supplier) assertEquals(f(42), F(42), 0.01f, supplier) assertEquals(F(42), f(42), 0.01f, supplier) assertEquals(F(42), F(42), 0.01f, supplier) } @Test void "bytes can be passed to assertEquals"() { assertEquals(b(42), b(42)) assertEquals(b(42), B(42)) assertEquals(B(42), b(42)) assertEquals(B(42), B(42)) assertEquals(b(42), b(42), '') assertEquals(b(42), B(42), '') assertEquals(B(42), b(42), '') assertEquals(B(42), B(42), '') assertEquals(b(42), b(42), supplier) assertEquals(b(42), B(42), supplier) assertEquals(B(42), b(42), supplier) assertEquals(B(42), B(42), supplier) } @Test void "doubles can be passed to assertEquals"() { assertEquals(d(42), d(42)) assertEquals(d(42), D(42)) assertEquals(D(42), d(42)) assertEquals(D(42), D(42)) assertEquals(d(42), d(42), '') assertEquals(d(42), D(42), '') assertEquals(D(42), d(42), '') assertEquals(D(42), D(42), '') assertEquals(d(42), d(42), supplier) assertEquals(d(42), D(42), supplier) assertEquals(D(42), d(42), supplier) assertEquals(D(42), D(42), supplier) } @Test void "doubles can be passed to assertEquals with delta"() { assertEquals(d(42), d(42), 0.01d) assertEquals(d(42), D(42), 0.01d) assertEquals(D(42), d(42), 0.01d) assertEquals(D(42), D(42), 0.01d) assertEquals(d(42), d(42), 0.01d, '') assertEquals(d(42), D(42), 0.01d, '') assertEquals(D(42), d(42), 0.01d, '') assertEquals(D(42), D(42), 0.01d, '') assertEquals(d(42), d(42), 0.01d, supplier) assertEquals(d(42), D(42), 0.01d, supplier) assertEquals(D(42), d(42), 0.01d, supplier) assertEquals(D(42), D(42), 0.01d, supplier) } @Test void "chars can be passed to assertEquals"() { assertEquals(c(42), c(42)) assertEquals(c(42), C(42)) assertEquals(C(42), c(42)) assertEquals(C(42), C(42)) assertEquals(c(42), c(42), '') assertEquals(c(42), C(42), '') assertEquals(C(42), c(42), '') assertEquals(C(42), C(42), '') assertEquals(c(42), c(42), supplier) assertEquals(c(42), C(42), supplier) assertEquals(C(42), c(42), supplier) assertEquals(C(42), C(42), supplier) } @Test void "longs can be passed to assertEquals"() { assertEquals(l(42), l(42)) assertEquals(l(42), L(42)) assertEquals(L(42), l(42)) assertEquals(L(42), L(42)) assertEquals(l(42), l(42), '') assertEquals(l(42), L(42), '') assertEquals(L(42), l(42), '') assertEquals(L(42), L(42), '') assertEquals(l(42), l(42), supplier) assertEquals(l(42), L(42), supplier) assertEquals(L(42), l(42), supplier) assertEquals(L(42), L(42), supplier) } @Test void "shorts can be passed to assertEquals"() { assertEquals(s(42), s(42)) assertEquals(s(42), S(42)) assertEquals(S(42), s(42)) assertEquals(S(42), S(42)) assertEquals(s(42), s(42), '') assertEquals(s(42), S(42), '') assertEquals(S(42), s(42), '') assertEquals(S(42), S(42), '') assertEquals(s(42), s(42), supplier) assertEquals(s(42), S(42), supplier) assertEquals(S(42), s(42), supplier) assertEquals(S(42), S(42), supplier) } } GroovyAssertNotEqualsTests.groovy000066400000000000000000000144321455764576500352730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/jupiter/api/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api import org.opentest4j.AssertionFailedError import java.util.function.Supplier import static org.junit.jupiter.api.Assertions.assertNotEquals import static org.junit.jupiter.api.Assertions.assertThrows import static org.junit.jupiter.api.PrimitiveAndWrapperTypeHelpers.* class GroovyAssertNotEqualsTests { Supplier supplier = { '' } @Test void "null references can be passed to assertNotEquals"() { Object null1 = null Object null2 = null assertThrows(AssertionFailedError, { assertNotEquals(null1, null) } ) assertThrows(AssertionFailedError, { assertNotEquals(null, null2) } ) assertThrows(AssertionFailedError, { assertNotEquals(null1, null2) } ) } @Test void "integers can be passed to assertNotEquals"() { assertNotEquals(i(42), i(2)) assertNotEquals(i(42), I(2)) assertNotEquals(I(42), i(2)) assertNotEquals(I(42), I(2)) assertNotEquals(i(42), i(2), '') assertNotEquals(i(42), I(2), '') assertNotEquals(I(42), i(2), '') assertNotEquals(I(42), I(2), '') assertNotEquals(i(42), i(2), supplier) assertNotEquals(i(42), I(2), supplier) assertNotEquals(I(42), i(2), supplier) assertNotEquals(I(42), I(2), supplier) } @Test void "floats can be passed to assertNotEquals"() { assertNotEquals(f(42), f(2)) assertNotEquals(f(42), F(2)) assertNotEquals(F(42), f(2)) assertNotEquals(F(42), F(2)) assertNotEquals(f(42), f(2), '') assertNotEquals(f(42), F(2), '') assertNotEquals(F(42), f(2), '') assertNotEquals(F(42), F(2), '') assertNotEquals(f(42), f(2), supplier) assertNotEquals(f(42), F(2), supplier) assertNotEquals(F(42), f(2), supplier) assertNotEquals(F(42), F(2), supplier) } @Test void "floats can be passed to assertNotEquals with delta"() { assertNotEquals(f(42), f(2), 0.01f) assertNotEquals(f(42), F(2), 0.01f) assertNotEquals(F(42), f(2), 0.01f) assertNotEquals(F(42), F(2), 0.01f) assertNotEquals(f(42), f(2), 0.01f, '') assertNotEquals(f(42), F(2), 0.01f, '') assertNotEquals(F(42), f(2), 0.01f, '') assertNotEquals(F(42), F(2), 0.01f, '') assertNotEquals(f(42), f(2), 0.01f, supplier) assertNotEquals(f(42), F(2), 0.01f, supplier) assertNotEquals(F(42), f(2), 0.01f, supplier) assertNotEquals(F(42), F(2), 0.01f, supplier) } @Test void "bytes can be passed to assertNotEquals"() { assertNotEquals(b(42), b(2)) assertNotEquals(b(42), B(2)) assertNotEquals(B(42), b(2)) assertNotEquals(B(42), B(2)) assertNotEquals(b(42), b(2), '') assertNotEquals(b(42), B(2), '') assertNotEquals(B(42), b(2), '') assertNotEquals(B(42), B(2), '') assertNotEquals(b(42), b(2), supplier) assertNotEquals(b(42), B(2), supplier) assertNotEquals(B(42), b(2), supplier) assertNotEquals(B(42), B(2), supplier) } @Test void "doubles can be passed to assertNotEquals"() { assertNotEquals(d(42), d(2)) assertNotEquals(d(42), D(2)) assertNotEquals(D(42), d(2)) assertNotEquals(D(42), D(2)) assertNotEquals(d(42), d(2), '') assertNotEquals(d(42), D(2), '') assertNotEquals(D(42), d(2), '') assertNotEquals(D(42), D(2), '') assertNotEquals(d(42), d(2), supplier) assertNotEquals(d(42), D(2), supplier) assertNotEquals(D(42), d(2), supplier) assertNotEquals(D(42), D(2), supplier) } @Test void "doubles can be passed to assertNotEquals with delta"() { assertNotEquals(d(42), d(2), 0.01d) assertNotEquals(d(42), D(2), 0.01d) assertNotEquals(D(42), d(2), 0.01d) assertNotEquals(D(42), D(2), 0.01d) assertNotEquals(d(42), d(2), 0.01d, '') assertNotEquals(d(42), D(2), 0.01d, '') assertNotEquals(D(42), d(2), 0.01d, '') assertNotEquals(D(42), D(2), 0.01d, '') assertNotEquals(d(42), d(2), 0.01d, supplier) assertNotEquals(d(42), D(2), 0.01d, supplier) assertNotEquals(D(42), d(2), 0.01d, supplier) assertNotEquals(D(42), D(2), 0.01d, supplier) } @Test void "chars can be passed to assertNotEquals"() { assertNotEquals(c(42), c(2)) assertNotEquals(c(42), C(2)) assertNotEquals(C(42), c(2)) assertNotEquals(C(42), C(2)) assertNotEquals(c(42), c(2), '') assertNotEquals(c(42), C(2), '') assertNotEquals(C(42), c(2), '') assertNotEquals(C(42), C(2), '') assertNotEquals(c(42), c(2), supplier) assertNotEquals(c(42), C(2), supplier) assertNotEquals(C(42), c(2), supplier) assertNotEquals(C(42), C(2), supplier) } @Test void "longs can be passed to assertNotEquals"() { assertNotEquals(l(42), l(2)) assertNotEquals(l(42), L(2)) assertNotEquals(L(42), l(2)) assertNotEquals(L(42), L(2)) assertNotEquals(l(42), l(2), '') assertNotEquals(l(42), L(2), '') assertNotEquals(L(42), l(2), '') assertNotEquals(L(42), L(2), '') assertNotEquals(l(42), l(2), supplier) assertNotEquals(l(42), L(2), supplier) assertNotEquals(L(42), l(2), supplier) assertNotEquals(L(42), L(2), supplier) } @Test void "shorts can be passed to assertNotEquals"() { assertNotEquals(s(42), s(2)) assertNotEquals(s(42), S(2)) assertNotEquals(S(42), s(2)) assertNotEquals(S(42), S(2)) assertNotEquals(s(42), s(2), '') assertNotEquals(s(42), S(2), '') assertNotEquals(S(42), s(2), '') assertNotEquals(S(42), S(2), '') assertNotEquals(s(42), s(2), supplier) assertNotEquals(s(42), S(2), supplier) assertNotEquals(S(42), s(2), supplier) assertNotEquals(S(42), S(2), supplier) } } PrimitiveAndWrapperTypeHelpers.groovy000066400000000000000000000026661455764576500360740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/groovy/org/junit/jupiter/api/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api class PrimitiveAndWrapperTypeHelpers { static char c(int number) { return (char) number } static Character C(int number) { return Character.valueOf((char) number) } static byte b(int number) { return (byte) number } static Byte B(int number) { return Byte.valueOf((byte) number) } static double d(int number) { return (double) number } static Double D(int number) { return Double.valueOf((double) number) } static float f(int number) { return (float) number } static Float F(int number) { return Float.valueOf((float) number) } static long l(int number) { return (long) number } static Long L(int number) { return Long.valueOf( (long) number) } static short s(int number) { return (short) number } static Short S(int number) { return Short.valueOf( (short) number) } static int i(int number) { return number } static Integer I(int number) { return Integer.valueOf( number) } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/000077500000000000000000000000001455764576500217725ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/DefaultPackageTestCase.java000066400000000000000000000012271455764576500271330ustar00rootroot00000000000000 /* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Simple test case that is used to verify proper support for classpath scanning * within the default package. * * @since 5.0 */ @Disabled("Only used reflectively by other tests") class DefaultPackageTestCase { @Test void test() { // do nothing } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/example/000077500000000000000000000000001455764576500234255ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/example/B_TestCase.java000066400000000000000000000013531455764576500262460ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package example; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; /** * @since 5.8 */ public class B_TestCase { public static List callSequence; @BeforeEach void trackInvocations(TestInfo testInfo) { if (callSequence != null) { callSequence.add(testInfo.getTestClass().get().getName()); } } @Test void a() { } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/000077500000000000000000000000001455764576500225615ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/000077500000000000000000000000001455764576500237125ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/000077500000000000000000000000001455764576500253745ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/JupiterTestSuite.java000066400000000000000000000022401455764576500315310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; /** * Test suite for the JUnit Jupiter programming model, extension model, and * {@code TestEngine} implementation. * *

Logging Configuration

* *

In order for our log4j2 configuration to be used in an IDE, you must * set the following system property before running any tests — for * example, in Run Configurations in Eclipse. * *

 * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
 * 
* * @since 5.0 */ @Suite @SelectPackages("org.junit.jupiter") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") class JupiterTestSuite { } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/000077500000000000000000000000001455764576500261455ustar00rootroot00000000000000AssertAllAssertionsTests.java000066400000000000000000000160571455764576500337320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.PreconditionViolationException; import org.opentest4j.AssertionFailedError; import org.opentest4j.MultipleFailuresError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertAllAssertionsTests { @Test void assertAllWithNullExecutableArray() { assertPrecondition("executables array must not be null or empty", () -> assertAll((Executable[]) null)); } @Test void assertAllWithNullExecutableCollection() { assertPrecondition("executables collection must not be null", () -> assertAll((Collection) null)); } @Test void assertAllWithNullExecutableStream() { assertPrecondition("executables stream must not be null", () -> assertAll((Stream) null)); } @Test void assertAllWithNullInExecutableArray() { assertPrecondition("individual executables must not be null", () -> assertAll((Executable) null)); } @Test void assertAllWithNullInExecutableCollection() { assertPrecondition("individual executables must not be null", () -> assertAll(asList((Executable) null))); } @Test void assertAllWithNullInExecutableStream() { assertPrecondition("individual executables must not be null", () -> assertAll(Stream.of((Executable) null))); } @Test void assertAllWithExecutablesThatDoNotThrowExceptions() { // @formatter:off assertAll( () -> assertTrue(true), () -> assertFalse(false) ); assertAll("heading", () -> assertTrue(true), () -> assertFalse(false) ); assertAll(asList( () -> assertTrue(true), () -> assertFalse(false) )); assertAll("heading", asList( () -> assertTrue(true), () -> assertFalse(false) )); assertAll(Stream.of( () -> assertTrue(true), () -> assertFalse(false) )); assertAll("heading", Stream.of( () -> assertTrue(true), () -> assertFalse(false) )); // @formatter:on } @Test void assertAllWithExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll( () -> assertFalse(true), () -> assertFalse(true) ) ); // @formatter:on assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError.class, AssertionFailedError.class); } @Test void assertAllWithCollectionOfExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(asList( () -> assertFalse(true), () -> assertFalse(true) )) ); // @formatter:on assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError.class, AssertionFailedError.class); } @Test void assertAllWithStreamOfExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(Stream.of( () -> assertFalse(true), () -> assertFalse(true) )) ); // @formatter:on assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError.class, AssertionFailedError.class); } @Test void assertAllWithExecutableThatThrowsThrowable() { MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(() -> { throw new EnigmaThrowable(); })); assertExpectedExceptionTypes(multipleFailuresError, EnigmaThrowable.class); } @Test void assertAllWithExecutableThatThrowsCheckedException() { MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(() -> { throw new IOException(); })); assertExpectedExceptionTypes(multipleFailuresError, IOException.class); } @Test void assertAllWithExecutableThatThrowsRuntimeException() { MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(() -> { throw new IllegalStateException(); })); assertExpectedExceptionTypes(multipleFailuresError, IllegalStateException.class); } @Test void assertAllWithExecutableThatThrowsError() { MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(AssertionTestUtils::recurseIndefinitely)); assertExpectedExceptionTypes(multipleFailuresError, StackOverflowError.class); } @Test void assertAllWithExecutableThatThrowsUnrecoverableException() { OutOfMemoryError outOfMemoryError = assertThrows(OutOfMemoryError.class, () -> assertAll(AssertionTestUtils::runOutOfMemory)); assertEquals("boom", outOfMemoryError.getMessage()); } @Test void assertAllWithParallelStream() { Executable executable = () -> { throw new RuntimeException(); }; MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(Stream.generate(() -> executable).parallel().limit(100))); assertThat(multipleFailuresError.getFailures()).hasSize(100).doesNotContainNull(); } private void assertPrecondition(String msg, Executable executable) { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, executable); assertMessageEquals(exception, msg); } @SafeVarargs static void assertExpectedExceptionTypes(MultipleFailuresError multipleFailuresError, Class... exceptionTypes) { assertNotNull(multipleFailuresError, "MultipleFailuresError"); List failures = multipleFailuresError.getFailures(); assertEquals(exceptionTypes.length, failures.size(), "number of failures"); // Verify that exceptions are also present as suppressed exceptions. // https://github.com/junit-team/junit5/issues/1602 Throwable[] suppressed = multipleFailuresError.getSuppressed(); assertEquals(exceptionTypes.length, suppressed.length, "number of suppressed exceptions"); for (int i = 0; i < exceptionTypes.length; i++) { assertEquals(exceptionTypes[i], failures.get(i).getClass(), "exception type [" + i + "]"); assertEquals(exceptionTypes[i], suppressed[i].getClass(), "suppressed exception type [" + i + "]"); } } @SuppressWarnings("serial") private static class EnigmaThrowable extends Throwable { } } AssertArrayEqualsAssertionsTests.java000066400000000000000000001754621455764576500354610ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEndsWith; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertArrayEqualsAssertionsTests { @Test void assertArrayEqualsWithNulls() { assertArrayEquals((boolean[]) null, (boolean[]) null); assertArrayEquals((char[]) null, (char[]) null); assertArrayEquals((byte[]) null, (byte[]) null); assertArrayEquals((int[]) null, (int[]) null); assertArrayEquals((long[]) null, (long[]) null); assertArrayEquals((float[]) null, (float[]) null); assertArrayEquals((double[]) null, (double[]) null); assertArrayEquals((Object[]) null, (Object[]) null); } @Test void assertArrayEqualsBooleanArrays() { assertArrayEquals(new boolean[] {}, new boolean[] {}); assertArrayEquals(new boolean[] {}, new boolean[] {}, "message"); assertArrayEquals(new boolean[] {}, new boolean[] {}, () -> "message"); assertArrayEquals(new boolean[] { true }, new boolean[] { true }); assertArrayEquals(new boolean[] { false, true, false, false }, new boolean[] { false, true, false, false }); } @Test void assertArrayEqualsBooleanArrayVsNull() { try { assertArrayEquals(null, new boolean[] { true, false }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new boolean[] { true, false }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsBooleanArrayVsNullAndMessage() { try { assertArrayEquals(null, new boolean[] { true, false }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new boolean[] { true, false }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsBooleanArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new boolean[] { true, false }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new boolean[] { true, false }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsBooleanArraysOfDifferentLength() { try { assertArrayEquals(new boolean[] { true, false }, new boolean[] { true, false, true }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsBooleanArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new boolean[] { true, false, false }, new boolean[] { true }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <1>"); } } @Test void assertArrayEqualsBooleanArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new boolean[] { true }, new boolean[] { true, false }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <1> but was: <2>"); } } @Test void assertArrayEqualsDifferentBooleanArrays() { try { assertArrayEquals(new boolean[] { true, false, false }, new boolean[] { true, false, true }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: but was: "); } } @Test void assertArrayEqualsDifferentBooleanArraysAndMessage() { try { assertArrayEquals(new boolean[] { true, true }, new boolean[] { false, true }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [0], expected: but was: "); } } @Test void assertArrayEqualsDifferentBooleanArraysAndMessageSupplier() { try { assertArrayEquals(new boolean[] { false, false, false }, new boolean[] { false, true, true }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: but was: "); } } @Test void assertArrayEqualsCharArrays() { assertArrayEquals(new char[] {}, new char[] {}); assertArrayEquals(new char[] {}, new char[] {}, "message"); assertArrayEquals(new char[] {}, new char[] {}, () -> "message"); assertArrayEquals(new char[] { 'a' }, new char[] { 'a' }); assertArrayEquals(new char[] { 'j', 'u', 'n', 'i', 't' }, new char[] { 'j', 'u', 'n', 'i', 't' }); } @Test void assertArrayEqualsCharArrayVsNull() { try { assertArrayEquals(null, new char[] { 'a', 'z' }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new char[] { 'a', 'z' }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsCharArrayVsNullAndMessage() { try { assertArrayEquals(null, new char[] { 'a', 'b', 'z' }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new char[] { 'a', 'b', 'z' }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsCharArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new char[] { 'z', 'x', 'y' }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new char[] { 'z', 'x', 'y' }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsCharArraysOfDifferentLength() { try { assertArrayEquals(new char[] { 'q', 'w', 'e' }, new char[] { 'q', 'w' }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <3> but was: <2>"); } } @Test void assertArrayEqualsCharArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new char[] { 'a', 's', 'd' }, new char[] { 'd' }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <1>"); } } @Test void assertArrayEqualsCharArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new char[] { 'q' }, new char[] { 't', 'u' }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <1> but was: <2>"); } } @Test void assertArrayEqualsDifferentCharArrays() { try { assertArrayEquals(new char[] { 'a', 'b', 'c' }, new char[] { 'a', 'b', 'a' }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: but was: "); } } @Test void assertArrayEqualsDifferentCharArraysAndMessage() { try { assertArrayEquals(new char[] { 'z', 'x', 'c', 'v' }, new char[] { 'x', 'x', 'c', 'v' }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [0], expected: but was: "); } } @Test void assertArrayEqualsDifferentCharArraysAndMessageSupplier() { try { assertArrayEquals(new char[] { 'r', 't', 'y' }, new char[] { 'r', 'y', 'u' }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: but was: "); } } @Test void assertArrayEqualsByteArrays() { assertArrayEquals(new byte[] {}, new byte[] {}); assertArrayEquals(new byte[] {}, new byte[] {}, "message"); assertArrayEquals(new byte[] {}, new byte[] {}, () -> "message"); assertArrayEquals(new byte[] { 42 }, new byte[] { 42 }); assertArrayEquals(new byte[] { 1, 2, 3, 42 }, new byte[] { 1, 2, 3, 42 }); } @Test void assertArrayEqualsByteArrayVsNull() { try { assertArrayEquals(null, new byte[] { 7, 8, 9 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new byte[] { 7, 8, 9 }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsByteArrayVsNullAndMessage() { try { assertArrayEquals(null, new byte[] { 9, 8, 7 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new byte[] { 9, 8, 7 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsByteArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new byte[] { 10, 20, 30 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new byte[] { 10, 20, 30 }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsByteArraysOfDifferentLength() { try { assertArrayEquals(new byte[] { 1, 2, 100 }, new byte[] { 1, 2, 100, 101 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <3> but was: <4>"); } } @Test void assertArrayEqualsByteArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new byte[] { 1, 2 }, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <9>"); } } @Test void assertArrayEqualsByteArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new byte[] { 88, 99 }, new byte[] { 99, 88, 77 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsDifferentByteArrays() { try { assertArrayEquals(new byte[] { 12, 13, 12, 13 }, new byte[] { 12, 13, 12, 14 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3], expected: <13> but was: <14>"); } } @Test void assertArrayEqualsDifferentByteArraysAndMessage() { try { assertArrayEquals(new byte[] { 1, 2, 3, 4, 5 }, new byte[] { 1, 2, 3, 5, 5 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3], expected: <4> but was: <5>"); } } @Test void assertArrayEqualsDifferentByteArraysAndMessageSupplier() { try { assertArrayEquals(new byte[] { 127, 126, -128, +127 }, new byte[] { 127, 126, -128, -127 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3], expected: <127> but was: <-127>"); } } @Test void assertArrayEqualsShortArrays() { assertArrayEquals(new short[] {}, new short[] {}); assertArrayEquals(new short[] {}, new short[] {}, "message"); assertArrayEquals(new short[] {}, new short[] {}, () -> "message"); assertArrayEquals(new short[] { 999 }, new short[] { 999 }); assertArrayEquals(new short[] { 111, 222, 333, 444, 999 }, new short[] { 111, 222, 333, 444, 999 }); } @Test void assertArrayEqualsShortArrayVsNull() { try { assertArrayEquals(null, new short[] { 5, 10, 12 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new short[] { 5, 10, 12 }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsShortArrayVsNullAndMessage() { try { assertArrayEquals(null, new short[] { 128, 129, 130 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new short[] { -129, -130, -131 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsShortArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new short[] { 1, 2, 3, 4 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new short[] { -2000, 1, 2, 3, 4 }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsShortArraysOfDifferentLength() { try { assertArrayEquals(new short[] { 1, 2, 3, 4, 5, 6 }, new short[] { 1, 2, 3 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <6> but was: <3>"); } } @Test void assertArrayEqualsShortArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new short[] { 1, 2, 3, 10_000 }, new short[] { 10_000, 1, 2, 3, 4, 5, 6, 7 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <4> but was: <8>"); } } @Test void assertArrayEqualsShortArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new short[] { 150, 151 }, new short[] { 150, 151, 152 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsDifferentShortArrays() { try { assertArrayEquals(new short[] { 10, 100, 1000, 10000 }, new short[] { 1, 10, 100, 1000 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [0], expected: <10> but was: <1>"); } } @Test void assertArrayEqualsDifferentShortArraysAndMessage() { try { assertArrayEquals(new short[] { 1, 2, 100, -200 }, new short[] { 1, 2, 100, -500 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3], expected: <-200> but was: <-500>"); } } @Test void assertArrayEqualsDifferentShortArraysAndMessageSupplier() { try { assertArrayEquals(new short[] { 1000, 2000, +3000, 42 }, new short[] { 1000, 2000, -3000, 42 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [2], expected: <3000> but was: <-3000>"); } } @Test void assertArrayEqualsIntArrays() { assertArrayEquals(new int[] {}, new int[] {}); assertArrayEquals(new int[] {}, new int[] {}, "message"); assertArrayEquals(new int[] {}, new int[] {}, () -> "message"); assertArrayEquals(new int[] { Integer.MAX_VALUE }, new int[] { Integer.MAX_VALUE }); assertArrayEquals(new int[] { 1, 2, 3, 4, 5, 99_999 }, new int[] { 1, 2, 3, 4, 5, 99_999 }); } @Test void assertArrayEqualsIntArrayVsNull() { try { assertArrayEquals(null, new int[] { Integer.MIN_VALUE, 2, 10 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new int[] { Integer.MIN_VALUE, 2, 10 }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsIntArrayVsNullAndMessage() { try { assertArrayEquals(null, new int[] { 99_999, 88_888, 1 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new int[] { 99_999, 77_7777, 2 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsIntArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new int[] { 1, 10, 100, 1000, 10000, 100000 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new int[] { 100000, 10000, 1000, 100, 10, 1 }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsIntArraysOfDifferentLength() { try { assertArrayEquals(new int[] { 1, 2, 3, Integer.MIN_VALUE, 4 }, new int[] { 1, Integer.MAX_VALUE, 2 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <5> but was: <3>"); } } @Test void assertArrayEqualsIntArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new int[] { 100_000, 200_000, 1, 2 }, new int[] { 1, 2, 3 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <4> but was: <3>"); } } @Test void assertArrayEqualsIntArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE }, new int[] { 1, 2, 3 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsDifferentIntArrays() { try { assertArrayEquals(new int[] { Integer.MIN_VALUE, 1, 2, 10 }, new int[] { Integer.MIN_VALUE, 1, 10, 10 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: <2> but was: <10>"); } } @Test void assertArrayEqualsDifferentIntArraysAndMessage() { try { assertArrayEquals(new int[] { 9, 10, 100, 100_000, 7 }, new int[] { 9, 10, 100, 100_000, 200_000 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [4], expected: <7> but was: <200000>"); } } @Test void assertArrayEqualsDifferentIntArraysAndMessageSupplier() { try { assertArrayEquals(new int[] { 1, Integer.MIN_VALUE, 2 }, new int[] { 1, Integer.MAX_VALUE, 2 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <-2147483648> but was: <2147483647>"); } } @Test void assertArrayEqualsLongArrays() { assertArrayEquals(new long[] {}, new long[] {}); assertArrayEquals(new long[] {}, new long[] {}, "message"); assertArrayEquals(new long[] {}, new long[] {}, () -> "message"); assertArrayEquals(new long[] { Long.MAX_VALUE }, new long[] { Long.MAX_VALUE }); assertArrayEquals(new long[] { Long.MIN_VALUE, 10, 20, 30 }, new long[] { Long.MIN_VALUE, 10, 20, 30 }); } @Test void assertArrayEqualsLongArrayVsNull() { try { assertArrayEquals(null, new long[] { Long.MAX_VALUE, 2, 10 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new long[] { Long.MAX_VALUE, 2, 10 }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsLongArrayVsNullAndMessage() { try { assertArrayEquals(null, new long[] { 42, 4242, 424242, 4242424242L }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new long[] { 4242424242L, 424242, 4242, 42 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsLongArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new long[] { 12345678910L, 10, 9, 8 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new long[] { 8, 9, 10, 12345678910L }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsLongArraysOfDifferentLength() { try { assertArrayEquals(new long[] { 1, 2, 3, Long.MIN_VALUE, 4 }, new long[] { 1, Long.MAX_VALUE, 2 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <5> but was: <3>"); } } @Test void assertArrayEqualsLongArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new long[] { 100_000L, 200_000L, 1L, 2L }, new long[] { 1L, 2L, 3L }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <4> but was: <3>"); } } @Test void assertArrayEqualsLongArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new long[] { Long.MAX_VALUE, Long.MIN_VALUE }, new long[] { 1L, 2L, 42L }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsDifferentLongArrays() { try { assertArrayEquals(new long[] { Long.MIN_VALUE, 17, 18L, 19 }, new long[] { Long.MIN_VALUE, 17, 18, 20 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3], expected: <19> but was: <20>"); } } @Test void assertArrayEqualsDifferentLongArraysAndMessage() { try { assertArrayEquals(new long[] { 6, 5, 4, 3, 2, Long.MIN_VALUE }, new long[] { 6, 5, 4, 3, 2, 1 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [5], expected: <-9223372036854775808> but was: <1>"); } } @Test void assertArrayEqualsDifferentLongArraysAndMessageSupplier() { try { assertArrayEquals(new long[] { 42, -9999L, 2 }, new long[] { 42L, +9999L, 2L }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <-9999> but was: <9999>"); } } @Test void assertArrayEqualsFloatArrays() { assertArrayEquals(new float[] {}, new float[] {}); assertArrayEquals(new float[] {}, new float[] {}, "message"); assertArrayEquals(new float[] {}, new float[] {}, () -> "message"); assertArrayEquals(new float[] { Float.MAX_VALUE }, new float[] { Float.MAX_VALUE }); assertArrayEquals(new float[] { Float.MIN_VALUE, 5F, 5.5F, 1.00F }, new float[] { Float.MIN_VALUE, 5F, 5.5F, 1.00F }); assertArrayEquals(new float[] { Float.NaN }, new float[] { Float.NaN }); assertArrayEquals(new float[] { 10.18F, Float.NaN, 42.9F }, new float[] { 10.18F, Float.NaN, 42.9F }); } @Test void assertArrayEqualsFloatArrayVsNull() { try { assertArrayEquals(null, new float[] { Float.MAX_VALUE, 4.2F, 9.0F }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new float[] { Float.MIN_VALUE, 2.3F, 10.10F }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsFloatArrayVsNullAndMessage() { try { assertArrayEquals(null, new float[] { 42.42F, 42.4242F, 19.20F }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new float[] { 11.101F, 12.101F, 99.9F }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsFloatArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new float[] { 5F, 6F, 7.77F, 8.88F }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new float[] { 1F, 1.1F, 1.11F, 1.111F }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsFloatArraysOfDifferentLength() { try { assertArrayEquals(new float[] { Float.MIN_VALUE, 1F, 2F, 3F }, new float[] { Float.MAX_VALUE, 7.1F }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <4> but was: <2>"); } } @Test void assertArrayEqualsFloatArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new float[] { 19.1F, 12.77F, 18.F }, new float[] { .9F, .8F, 5.123F, .10F }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <4>"); } } @Test void assertArrayEqualsFloatArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new float[] { 1.1F, 1.2F, 1.3F }, new float[] { 1F, 2F, 3F, 4F, 5F, 6F }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <6>"); } } @Test void assertArrayEqualsDifferentFloatArrays() { try { assertArrayEquals(new float[] { 5.5F, 6.5F, 7.5F, 8.5F }, new float[] { 5.5F, 6.5F, 7.4F, 8.5F }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: <7.5> but was: <7.4>"); } try { assertArrayEquals(new float[] { 1.0F, 2.0F, 3.0F, Float.NaN }, new float[] { 1.0F, 2.0F, 3.0F, 4.0F }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3], expected: but was: <4.0>"); } } @Test void assertArrayEqualsDifferentFloatArraysAndMessage() { try { assertArrayEquals(new float[] { 1.9F, 0.5F, 0.4F, 0.3F }, new float[] { 1.9F, 0.5F, 0.4F, -0.333F }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3], expected: <0.3> but was: <-0.333>"); } } @Test void assertArrayEqualsDifferentFloatArraysAndMessageSupplier() { try { assertArrayEquals(new float[] { 0.3F, 0.9F, 8F }, new float[] { 0.3F, Float.MIN_VALUE, 8F }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <0.9> but was: <1.4E-45>"); } } @Test void assertArrayEqualsDeltaFloatArrays() { assertArrayEquals(new float[] {}, new float[] {}, 0.001F); assertArrayEquals(new float[] {}, new float[] {}, 0.001F, "message"); assertArrayEquals(new float[] {}, new float[] {}, 0.001F, () -> "message"); assertArrayEquals(new float[] { Float.MAX_VALUE }, new float[] { Float.MAX_VALUE }, 0.0001F); assertArrayEquals(new float[] { Float.MIN_VALUE, 2.111F, 2.521F, 1.01F }, new float[] { Float.MIN_VALUE, 2.119F, 2.523F, 1.01001F }, 0.01F); assertArrayEquals(new float[] { Float.NaN }, new float[] { Float.NaN }, 0.1F); assertArrayEquals(new float[] { 10.18F, Float.NaN, 42.9F }, new float[] { 10.98F, Float.NaN, 43.9F }, 1F); } @Test void assertArrayEqualsDeltaFloatArraysThrowsForIllegalDelta() { try { assertArrayEquals(new float[] {}, new float[] {}, -0.5F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: <-0.5>"); } try { assertArrayEquals(new float[] {}, new float[] {}, Float.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: "); } try { assertArrayEquals(new float[] { 12.9F, 7F, 13F }, new float[] { 12.9F, 7F, 13F }, -0.5F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: <-0.5>"); } try { assertArrayEquals(new float[] { 1.11F, 1.11F, 9F }, new float[] { 1.11F, 1.11F, 9F, 10F }, Float.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: "); } } @Test void assertArrayEqualsDeltaFloatArrayVsNull() { try { assertArrayEquals(null, new float[] { Float.MAX_VALUE, 4.2F, 9.0F }, 0.001F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new float[] { Float.MIN_VALUE, 2.3F, 10.10F }, null, 0.01F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaFloatArrayVsNullAndMessage() { try { assertArrayEquals(null, new float[] { 42.42F, 42.4242F, 19.20F }, 0.0001F, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new float[] { 11.101F, 12.101F, 99.9F }, null, 0.01F, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaFloatArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new float[] { 5F, 6F, 7.77F, 8.88F }, 0.1F, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new float[] { 1F, 1.1F, 1.11F, 1.111F }, null, 0.1F, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaFloatArraysOfDifferentLength() { try { assertArrayEquals(new float[] { Float.MIN_VALUE, 1F, 2F, 3F }, new float[] { Float.MAX_VALUE, 7.1F }, 0.1F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <4> but was: <2>"); } } @Test void assertArrayEqualsDeltaFloatArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new float[] { 19.1F, 12.77F }, new float[] { .9F, .8F, 5.123F }, 0.1F, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsDeltaFloatArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new float[] { 1.1F, 1.2F, 1.3F }, new float[] { 1F, 2F, 3F, 4F }, 0.1F, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <4>"); } } @Test void assertArrayEqualsDeltaDifferentFloatArrays() { try { assertArrayEquals(new float[] { 5.6F, 3.2F, 9.1F, 0.5F }, new float[] { 5.55F, 3.3F, 9.201F, 0.51F }, 0.1F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: <9.1> but was: <9.201>"); } try { assertArrayEquals(new float[] { 1.0F, 2.0F, 3.0F, Float.NaN }, new float[] { 1.5F, 1.5F, 2.9F, 4.0F }, 0.5F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3], expected: but was: <4.0>"); } } @Test void assertArrayEqualsDeltaDifferentFloatArraysAndMessage() { try { assertArrayEquals(new float[] { 1.91F, 0.5F, .4F, 0.3F }, new float[] { 2F, 0.509F, .499F, -0.333F }, 0.1F, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3], expected: <0.3> but was: <-0.333>"); } } @Test void assertArrayEqualsDeltaDifferentFloatArraysAndMessageSupplier() { try { assertArrayEquals(new float[] { 0.3F, 0.9F, 8F }, new float[] { 0.6F, Float.MIN_VALUE, 8.4F }, 0.5F, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <0.9> but was: <1.4E-45>"); } } @Test void assertArrayEqualsDoubleArrays() { assertArrayEquals(new double[] {}, new double[] {}); assertArrayEquals(new double[] {}, new double[] {}, "message"); assertArrayEquals(new double[] {}, new double[] {}, () -> "message"); assertArrayEquals(new double[] { Double.MAX_VALUE }, new double[] { Double.MAX_VALUE }); assertArrayEquals(new double[] { Double.MIN_VALUE, 2.1, 5.5, 1.0 }, new double[] { Double.MIN_VALUE, 2.1, 5.5, 1.0 }); assertArrayEquals(new double[] { Double.NaN }, new double[] { Double.NaN }); assertArrayEquals(new double[] { 1.2, 10.8, Double.NaN, 42.9 }, new double[] { 1.2, 10.8, Double.NaN, 42.9 }); } @Test void assertArrayEqualsDoubleArrayVsNull() { try { assertArrayEquals(null, new double[] { Double.MAX_VALUE, 17.4, 98.7654321 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new double[] { Double.MIN_VALUE, 93.0, 92.000001 }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsDoubleArrayVsNullAndMessage() { try { assertArrayEquals(null, new double[] { 33.3, 34.9, 20.1, 11.0011 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new double[] { 44.4, 20.19, 11.3, 0.11 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDoubleArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new double[] { 1.2, 1.3, 1.4, 2.2002 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new double[] { 13.13, 43.33, 100 }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDoubleArraysOfDifferentLength() { try { assertArrayEquals(new double[] { Double.MIN_VALUE, 1.0, 2.0, 3.0 }, new double[] { Double.MAX_VALUE, 1.1, 1.0 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <4> but was: <3>"); } } @Test void assertArrayEqualsDoubleArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new double[] { 11.1, 99.1, 2 }, new double[] { .9, .1, .0, .1, .3 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <5>"); } } @Test void assertArrayEqualsDoubleArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new double[] { 1.15D, 2.2, 2.3 }, new double[] { 1.15D, 1.15D }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <2>"); } } @Test void assertArrayEqualsDifferentDoubleArrays() { try { assertArrayEquals(new double[] { 1.17, 1.19, 1.21, 5 }, new double[] { 1.17, 1.00019, 1.21, 5 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [1], expected: <1.19> but was: <1.00019>"); } try { assertArrayEquals(new double[] { 0.1, 0.2, 0.3, 0.4, 0.5 }, new double[] { 0.1, 0.2, 0.3, 0.4, Double.NaN }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [4], expected: <0.5> but was: "); } } @Test void assertArrayEqualsDifferentDoubleArraysAndMessage() { try { assertArrayEquals(new double[] { 1.01, 9.031, .123, 4.23 }, new double[] { 1.01, 9.099, .123, 4.23 }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <9.031> but was: <9.099>"); } } @Test void assertArrayEqualsDifferentDoubleArraysAndMessageSupplier() { try { assertArrayEquals(new double[] { 0.7, .1, 8 }, new double[] { 0.7, Double.MIN_VALUE, 8 }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <0.1> but was: <4.9E-324>"); } } @Test void assertArrayEqualsDeltaDoubleArrays() { assertArrayEquals(new double[] {}, new double[] {}, 0.5); assertArrayEquals(new double[] {}, new double[] {}, 0.5, "message"); assertArrayEquals(new double[] {}, new double[] {}, 0.5, () -> "message"); assertArrayEquals(new double[] { Double.MAX_VALUE, 0.1 }, new double[] { Double.MAX_VALUE, 0.2 }, 0.2); assertArrayEquals(new double[] { Double.MIN_VALUE, 3.1, 1.3, 2.7 }, new double[] { Double.MIN_VALUE, 3.4, 1.7, 2.4 }, 0.5); assertArrayEquals(new double[] { Double.NaN }, new double[] { Double.NaN }, 0.01); assertArrayEquals(new double[] { 1.2, 1.8, Double.NaN, 4.9 }, new double[] { 1.25, 1.7, Double.NaN, 4.8 }, 0.2); } @Test void assertArrayEqualsDeltaDoubleArraysThrowsForIllegalDelta() { try { assertArrayEquals(new double[] {}, new double[] {}, -0.5F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: <-0.5>"); } try { assertArrayEquals(new double[] {}, new double[] {}, Float.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: "); } try { assertArrayEquals(new double[] { 1.2, 1.3, 10 }, new double[] { 1.2, 1.3, 10 }, -0.5F); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: <-0.5>"); } try { assertArrayEquals(new double[] { 0.1, 10 }, new double[] { 0.1, 10, 11 }, Float.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "positive delta expected but was: "); } } @Test void assertArrayEqualsDeltaDoubleArrayVsNull() { try { assertArrayEquals(null, new double[] { Double.MAX_VALUE, 11.1, 12.12 }, 0.5); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new double[] { Double.MIN_VALUE, 90, 91.9 }, null, 0.1); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaDoubleArrayVsNullAndMessage() { try { assertArrayEquals(null, new double[] { 33.3, 34.9, 20.1, 11.0011 }, 0.1, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new double[] { 44.4, 20.19, 11.3, 0.11 }, null, 0.5, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaDoubleArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new double[] { 1.2, 1.3, 1.4, 2.2002 }, 1, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new double[] { 13.13, 43.33, 100 }, null, 1.5, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsDeltaDoubleArraysOfDifferentLength() { try { assertArrayEquals(new double[] { Double.MIN_VALUE, 2.0, 3.0, 4.0 }, new double[] { Double.MAX_VALUE, 2.1, 3.1 }, 0.001); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <4> but was: <3>"); } } @Test void assertArrayEqualsDeltaDoubleArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new double[] { 1.1, 99.1, 3.1 }, new double[] { .9, .1, .0, .1, .3 }, 0.1, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <5>"); } } @Test void assertArrayEqualsDeltaDoubleArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new double[] { 1.77D, 2.1, 3 }, new double[] { 8.8, 0.11 }, 1, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <2>"); } } @Test void assertArrayEqualsDeltaDifferentDoubleArrays() { try { assertArrayEquals(new double[] { 1.12, 2.92, 1.201 }, new double[] { 1.1201, 2.94, 1.201 }, 0.01); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [1], expected: <2.92> but was: <2.94>"); } try { assertArrayEquals(new double[] { 0.6, 0.12, 19.9, 5.5 }, new double[] { 1.0, 0.42, 20, Double.NaN }, 0.5); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3], expected: <5.5> but was: "); } } @Test void assertArrayEqualsDeltaDifferentDoubleArraysAndMessage() { try { assertArrayEquals(new double[] { 1.01, 9.031, .123, 4.23 }, new double[] { 1.1, 9.231, .13, 4.3 }, 0.1, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <9.031> but was: <9.231>"); } } @Test void assertArrayEqualsDeltaDifferentDoubleArraysAndMessageSupplier() { try { assertArrayEquals(new double[] { 0.7, 0.3001, 8 }, new double[] { 0.7, 0.4002, 8 }, 0.1, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [1], expected: <0.3001> but was: <0.4002>"); } } @Test void assertArrayEqualsObjectArrays() { Object[] array = { "a", 'b', 1, 2 }; assertArrayEquals(array, array); assertArrayEquals(new Object[] {}, new Object[] {}); assertArrayEquals(new Object[] {}, new Object[] {}, "message"); assertArrayEquals(new Object[] {}, new Object[] {}, () -> "message"); assertArrayEquals(new Object[] { "abc" }, new Object[] { "abc" }); assertArrayEquals(new Object[] { "abc", 1, 2L, 3D }, new Object[] { "abc", 1, 2L, 3D }); assertArrayEquals(new Object[] { new Object[] { new Object[] {} } }, new Object[] { new Object[] { new Object[] {} } }); assertArrayEquals( new Object[] { null, new Object[] { null, new Object[] { null, null } }, null, new Object[] { null } }, new Object[] { null, new Object[] { null, new Object[] { null, null } }, null, new Object[] { null } }); assertArrayEquals(new Object[] { "a", new Object[] { new Object[] { "b", new Object[] { "c", "d" } } }, "e" }, new Object[] { "a", new Object[] { new Object[] { "b", new Object[] { "c", "d" } } }, "e" }); assertArrayEquals( new Object[] { new Object[] { 1 }, new Object[] { 2 }, new Object[] { new Object[] { 3, new Object[] { 4 } } } }, new Object[] { new Object[] { 1 }, new Object[] { 2 }, new Object[] { new Object[] { 3, new Object[] { 4 } } } }); assertArrayEquals( new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { "abc" } } } } } } }, new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { "abc" } } } } } } }); assertArrayEquals( new Object[] { null, new Object[] { null, Double.NaN, new Object[] { Float.NaN, null, new Object[] {} } } }, new Object[] { null, new Object[] { null, Double.NaN, new Object[] { Float.NaN, null, new Object[] {} } } }); assertArrayEquals( new Object[] { new String("a"), Integer.valueOf(1), new Object[] { Double.parseDouble("1.1"), "b" } }, new Object[] { new String("a"), Integer.valueOf(1), new Object[] { Double.parseDouble("1.1"), "b" } }); assertArrayEquals( new Object[] { 1, 2, new Object[] { 3, new int[] { 4, 5 }, new long[] { 6 }, new Object[] { new Object[] { new int[] { 7 } } } }, new int[] { 8 }, new Object[] { new long[] { 9 } } }, new Object[] { 1, 2, new Object[] { 3, new int[] { 4, 5 }, new long[] { 6 }, new Object[] { new Object[] { new int[] { 7 } } } }, new int[] { 8 }, new Object[] { new long[] { 9 } } }); assertArrayEquals( new Object[] { "a", new char[] { 'b', 'c' }, new int[] { 'd' }, new Object[] { new Object[] { new String[] { "ef" }, new Object[] { new String[] { "ghi" } } } } }, new Object[] { "a", new char[] { 'b', 'c' }, new int[] { 'd' }, new Object[] { new Object[] { new String[] { "ef" }, new Object[] { new String[] { "ghi" } } } } }); } @Test void assertArrayEqualsObjectArrayVsNull() { try { assertArrayEquals(null, new Object[] { "a", "b", 1, new Object() }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was "); } try { assertArrayEquals(new Object[] { 'a', 1, new Object(), 10L }, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was "); } } @Test void assertArrayEqualsNestedObjectArrayVsNull() { try { assertArrayEquals(// new Object[] { new Object[] {}, 1, "2", new Object[] { '3', new Object[] { null } } }, // new Object[] { new Object[] {}, 1, "2", new Object[] { '3', new Object[] { new Object[] { "4" } } } }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected array was at index [3][1][0]"); } try { assertArrayEquals( new Object[] { 1, 2, new Object[] { 3, new Object[] { "4", new Object[] { 5, new Object[] { 6 } } } }, "7" }, new Object[] { 1, 2, new Object[] { 3, new Object[] { "4", new Object[] { 5, null } } }, "7" }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual array was at index [2][1][1][1]"); } } @Test void assertArrayEqualsObjectArrayVsNullAndMessage() { try { assertArrayEquals(null, new Object[] { 'a', "b", 10, 20D }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new Object[] { "hello", 42 }, null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsNestedObjectArrayVsNullAndMessage() { try { assertArrayEquals(new Object[] { 1, new Object[] { 2, 3, new Object[] { 4, 5, new Object[] { null } } } }, new Object[] { 1, new Object[] { 2, 3, new Object[] { 4, 5, new Object[] { new Object[] { 6 } } } } }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was at index [1][2][2][0]"); } try { assertArrayEquals( new Object[] { 1, new Object[] { 2, new Object[] { 3, new Object[] { new Object[] { 4 } } } } }, new Object[] { 1, new Object[] { 2, new Object[] { 3, new Object[] { null } } } }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was at index [1][1][1][0]"); } } @Test void assertArrayEqualsObjectArrayVsNullAndMessageSupplier() { try { assertArrayEquals(null, new Object[] { 42, "42", new float[] { 42F }, 42D }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was "); } try { assertArrayEquals(new Object[] { new Object[] { "a" }, new Object() }, null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was "); } } @Test void assertArrayEqualsNestedObjectArrayVsNullAndMessageSupplier() { try { assertArrayEquals(new Object[] { "1", "2", "3", new Object[] { "4", new Object[] { null } } }, new Object[] { "1", "2", "3", new Object[] { "4", new Object[] { new int[] { 5 } } } }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected array was at index [3][1][0]"); } try { assertArrayEquals( new Object[] { 1, 2, new Object[] { "3", new Object[] { '4', new Object[] { 5, 6, new long[] {} } } } }, new Object[] { 1, 2, new Object[] { "3", new Object[] { '4', new Object[] { 5, 6, null } } } }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual array was at index [2][1][1][2]"); } } @Test void assertArrayEqualsObjectArraysOfDifferentLength() { try { assertArrayEquals(new Object[] { 'a', "b", 'c' }, new Object[] { 'a', "b", 'c', 1 }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ, expected: <3> but was: <4>"); } } @Test void assertArrayEqualsNestedObjectArraysOfDifferentLength() { try { assertArrayEquals( new Object[] { "a", new Object[] { "b", new Object[] { "c", "d", new Object[] { "e", 1, 2, 3 } } } }, new Object[] { "a", new Object[] { "b", new Object[] { "c", "d", new Object[] { "e", 1, 2, 3, 4, 5 } } } }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ at index [1][1][2], expected: <4> but was: <6>"); } try { assertArrayEquals( new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new char[] { 'a' } } } } } } }, new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new Object[] { new char[] { 'a', 'b' } } } } } } }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array lengths differ at index [0][0][0][0][0][0], expected: <1> but was: <2>"); } } @Test void assertArrayEqualsObjectArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(new Object[] { 'a', 1 }, new Object[] { 'a', 1, new Object() }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <2> but was: <3>"); } } @Test void assertArrayEqualsNestedObjectArraysOfDifferentLengthAndMessage() { try { assertArrayEquals(// new Object[] { 'a', 1, new Object[] { 2, 3 } }, // new Object[] { 'a', 1, new Object[] { 2, 3, 4, 5 } }, // "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ at index [2], expected: <2> but was: <4>"); } } @Test void assertArrayEqualsObjectArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(new Object[] { "a", "b", "c" }, new Object[] { "a", "b", "c", "d", "e", "f" }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ, expected: <3> but was: <6>"); } } @Test void assertArrayEqualsNestedObjectArraysOfDifferentLengthAndMessageSupplier() { try { assertArrayEquals(// new Object[] { "a", new Object[] { 1, 2, 3, new double[] { 4.0, 5.1, 6.1 }, 7 } }, // new Object[] { "a", new Object[] { 1, 2, 3, new double[] { 4.0, 5.1, 6.1, 7.0 }, 8 } }, // () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array lengths differ at index [1][3], expected: <3> but was: <4>"); } } @Test void assertArrayEqualsDifferentObjectArrays() { try { assertArrayEquals(new Object[] { 1L, "2", '3', 4, 5D }, new Object[] { 1L, "2", '9', 4, 5D }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2], expected: <3> but was: <9>"); } try { assertArrayEquals(new Object[] { "a", 10, 11, 12, Double.NaN }, new Object[] { "a", 10, 11, 12, 13.55D }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [4], expected: but was: <13.55>"); } } @Test void assertArrayEqualsDifferentNestedObjectArrays() { try { assertArrayEquals( new Object[] { 1, 2, new Object[] { 3, new Object[] { 4, new boolean[] { false, true } } } }, new Object[] { 1, 2, new Object[] { 3, new Object[] { 4, new boolean[] { true, false } } } }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [2][1][1][0], expected: but was: "); } try { assertArrayEquals(new Object[] { 1, 2, 3, new Object[] { new Object[] { 4, new Object[] { 5 } } } }, new Object[] { 1, 2, 3, new Object[] { new Object[] { 4, new Object[] { new Object[] {} } } } }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "array contents differ at index [3][0][1][0], expected: <5> but was: <[]>"); } } @Test void assertArrayEqualsDifferentObjectArraysAndMessage() { try { assertArrayEquals(new Object[] { 1.1D, 2L, "3" }, new Object[] { 1D, 2L, "3" }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [0], expected: <1.1> but was: <1.0>"); } } @Test void assertArrayEqualsDifferentNestedObjectArraysAndMessage() { try { assertArrayEquals(new Object[] { 9, 8, '6', new Object[] { 5, 4, "3", new Object[] { "2", '1' } } }, new Object[] { 9, 8, '6', new Object[] { 5, 4, "3", new Object[] { "99", '1' } } }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3][3][0], expected: <2> but was: <99>"); } try { assertArrayEquals(new Object[] { 9, 8, '6', new Object[] { 5, 4, "3", new String[] { "2", "1" } } }, new Object[] { 9, 8, '6', new Object[] { 5, 4, "3", new String[] { "99", "1" } } }, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [3][3][0], expected: <2> but was: <99>"); } } @Test void assertArrayEqualsDifferentObjectArraysAndMessageSupplier() { try { assertArrayEquals(new Object[] { "one", 1L, Double.MIN_VALUE, "abc" }, new Object[] { "one", 1L, 42.42, "abc" }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [2], expected: <4.9E-324> but was: <42.42>"); } } @Test void assertArrayEqualsDifferentNestedObjectArraysAndMessageSupplier() { try { assertArrayEquals( new Object[] { "one", 1L, new Object[] { "a", 'b', new Object[] { 1, new Object[] { 2, 3 } } }, "abc" }, new Object[] { "one", 1L, new Object[] { "a", 'b', new Object[] { 1, new Object[] { 2, 4 } } }, "abc" }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [2][2][1][1], expected: <3> but was: <4>"); } try { assertArrayEquals( new Object[] { "j", new String[] { "a" }, new int[] { 42 }, "ab", new Object[] { 1, new int[] { 3 } } }, new Object[] { "j", new String[] { "a" }, new int[] { 42 }, "ab", new Object[] { 1, new int[] { 5 } } }, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "array contents differ at index [4][1][0], expected: <3> but was: <5>"); } } } AssertDoesNotThrowAssertionsTests.java000066400000000000000000000217451455764576500356210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.util.concurrent.FutureTask; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.2 */ class AssertDoesNotThrowAssertionsTests { private static final Executable nix = () -> { }; private static final ThrowingSupplier something = () -> "enigma"; @Test void assertDoesNotThrowWithMethodReferenceForNonVoidReturnType() { FutureTask future = new FutureTask<>(() -> { return "foo"; }); future.run(); String result; // Current compiler's type inference: does NOT compile since the compiler // cannot figure out which overloaded variant of assertDoesNotThrow() to // invoke (i.e., Executable vs. ThrowingSupplier). // // result = assertDoesNotThrow(future::get); // Explicitly as an Executable assertDoesNotThrow((Executable) future::get); // Explicitly as a ThrowingSupplier result = assertDoesNotThrow((ThrowingSupplier) future::get); assertEquals("foo", result); } @Test void assertDoesNotThrowWithMethodReferenceForVoidReturnType() { var foo = new Foo(); // Note: the following does not compile since the compiler cannot properly // perform type inference for a method reference for an overloaded method // that has a void return type such as Foo.overloaded(...), IFF the // compiler is simultaneously trying to pick which overloaded variant // of assertDoesNotThrow() to invoke. // // assertDoesNotThrow(foo::overloaded); // Current compiler's type inference assertDoesNotThrow(foo::normalMethod); // Explicitly as an Executable assertDoesNotThrow((Executable) foo::normalMethod); assertDoesNotThrow((Executable) foo::overloaded); } // --- executable ---------------------------------------------------------- @Test void assertDoesNotThrowAnythingWithExecutable() { assertDoesNotThrow(nix); } @Test void assertDoesNotThrowAnythingWithExecutableAndMessage() { assertDoesNotThrow(nix, "message"); } @Test void assertDoesNotThrowAnythingWithExecutableAndMessageSupplier() { assertDoesNotThrow(nix, () -> "message"); } @Test void assertDoesNotThrowWithExecutableThatThrowsACheckedException() { try { assertDoesNotThrow((Executable) () -> { throw new IOException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IOException.class.getName()); } } @Test void assertDoesNotThrowWithExecutableThatThrowsACheckedExceptionWithMessage() { String message = "Checked exception message"; try { assertDoesNotThrow((Executable) () -> { throw new IOException(message); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IOException.class.getName() + ": " + message); } } @Test void assertDoesNotThrowWithExecutableThatThrowsARuntimeException() { try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IllegalStateException.class.getName()); } } @Test void assertDoesNotThrowWithExecutableThatThrowsARuntimeExceptionWithMessage() { String message = "Runtime exception message"; try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(message); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IllegalStateException.class.getName() + ": " + message); } } @Test void assertDoesNotThrowWithExecutableThatThrowsAnError() { try { assertDoesNotThrow((Executable) AssertionTestUtils::recurseIndefinitely); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + StackOverflowError.class.getName()); } } @Test void assertDoesNotThrowWithExecutableThatThrowsAnExceptionWithMessageString() { try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(); }, "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName()); } } @Test void assertDoesNotThrowWithExecutableThatThrowsAnExceptionWithMessageWithMessageString() { String message = "Runtime exception message"; try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(message); }, "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName() + ": " + message); } } @Test void assertDoesNotThrowWithExecutableThatThrowsAnExceptionWithMessageSupplier() { try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(); }, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName()); } } @Test void assertDoesNotThrowWithExecutableThatThrowsAnExceptionWithMessageWithMessageSupplier() { String message = "Runtime exception message"; try { assertDoesNotThrow((Executable) () -> { throw new IllegalStateException(message); }, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName() + ": " + message); } } // --- supplier ------------------------------------------------------------ @Test void assertDoesNotThrowAnythingWithSupplier() { assertEquals("enigma", assertDoesNotThrow(something)); } @Test void assertDoesNotThrowAnythingWithSupplierAndMessage() { assertEquals("enigma", assertDoesNotThrow(something, "message")); } @Test void assertDoesNotThrowAnythingWithSupplierAndMessageSupplier() { assertEquals("enigma", assertDoesNotThrow(something, () -> "message")); } @Test void assertDoesNotThrowWithSupplierThatThrowsACheckedException() { try { assertDoesNotThrow((ThrowingSupplier) () -> { throw new IOException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IOException.class.getName()); } } @Test void assertDoesNotThrowWithSupplierThatThrowsARuntimeException() { try { assertDoesNotThrow((ThrowingSupplier) () -> { throw new IllegalStateException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + IllegalStateException.class.getName()); } } @Test void assertDoesNotThrowWithSupplierThatThrowsAnError() { try { assertDoesNotThrow((ThrowingSupplier) () -> { throw new StackOverflowError(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Unexpected exception thrown: " + StackOverflowError.class.getName()); } } @Test void assertDoesNotThrowWithSupplierThatThrowsAnExceptionWithMessageString() { try { assertDoesNotThrow((ThrowingSupplier) () -> { throw new IllegalStateException(); }, "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName()); } } @Test void assertDoesNotThrowWithSupplierThatThrowsAnExceptionWithMessageSupplier() { try { assertDoesNotThrow((ThrowingSupplier) () -> { throw new IllegalStateException(); }, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Custom message ==> Unexpected exception thrown: " + IllegalStateException.class.getName()); } } // ------------------------------------------------------------------------- private static class Foo { void normalMethod() { } void overloaded() { } @SuppressWarnings("unused") void overloaded(int i) { } } } AssertEqualsAssertionsTests.java000066400000000000000000000545041455764576500344530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertExpectedAndActualValues; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEndsWith; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.function.Executable; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertEqualsAssertionsTests { @Test void assertEqualsByte() { byte expected = 1; byte actual = 1; assertEquals(expected, actual); assertEquals(expected, actual, "message"); assertEquals(expected, actual, () -> "message"); } @Test void assertEqualsByteWithUnequalValues() { byte expected = 1; byte actual = 2; try { assertEquals(expected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsByteWithUnequalValuesAndMessage() { byte expected = 1; byte actual = 2; try { assertEquals(expected, actual, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsByteWithUnequalValuesAndMessageSupplier() { byte expected = 1; byte actual = 2; try { assertEquals(expected, actual, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsShort() { short expected = 1; short actual = 1; assertEquals(expected, actual); assertEquals(expected, actual, "message"); assertEquals(expected, actual, () -> "message"); } @Test void assertEqualsShortWithUnequalValues() { short expected = 1; short actual = 2; try { assertEquals(expected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsShortWithUnequalValuesAndMessage() { short expected = 1; short actual = 2; try { assertEquals(expected, actual, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsShortWithUnequalValuesAndMessageSupplier() { short expected = 1; short actual = 2; try { assertEquals(expected, actual, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, expected, actual); } } @Test void assertEqualsInt() { assertEquals(1, 1); assertEquals(1, 1, "message"); assertEquals(1, 1, () -> "message"); } @Test void assertEqualsIntWithUnequalValues() { try { assertEquals(1, 2); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1, 2); } } @Test void assertEqualsIntWithUnequalValuesAndMessage() { try { assertEquals(1, 2, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1, 2); } } @Test void assertEqualsIntWithUnequalValuesAndMessageSupplier() { try { assertEquals(1, 2, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1, 2); } } @Test void assertEqualsLong() { assertEquals(1L, 1L); assertEquals(1L, 1L, "message"); assertEquals(1L, 1L, () -> "message"); } @Test void assertEqualsLongWithUnequalValues() { try { assertEquals(1L, 2L); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1L, 2L); } } @Test void assertEqualsLongWithUnequalValuesAndMessage() { try { assertEquals(1L, 2L, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1L, 2L); } } @Test void assertEqualsLongWithUnequalValuesAndMessageSupplier() { try { assertEquals(1L, 2L, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1> but was: <2>"); assertExpectedAndActualValues(ex, 1L, 2L); } } @Test void assertEqualsChar() { assertEquals('a', 'a'); assertEquals('a', 'a', "message"); assertEquals('a', 'a', () -> "message"); } @Test void assertEqualsCharWithUnequalValues() { try { assertEquals('a', 'b'); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, 'a', 'b'); } } @Test void assertEqualsCharWithUnequalValuesAndMessage() { try { assertEquals('a', 'b', "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: but was: "); assertExpectedAndActualValues(ex, 'a', 'b'); } } @Test void assertEqualsCharWithUnequalValuesAndMessageSupplier() { try { assertEquals('a', 'b', () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: but was: "); assertExpectedAndActualValues(ex, 'a', 'b'); } } @Test void assertEqualsFloat() { assertEquals(1.0f, 1.0f); assertEquals(1.0f, 1.0f, "message"); assertEquals(1.0f, 1.0f, () -> "message"); assertEquals(Float.NaN, Float.NaN); assertEquals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); assertEquals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); assertEquals(Float.MIN_VALUE, Float.MIN_VALUE); assertEquals(Float.MAX_VALUE, Float.MAX_VALUE); assertEquals(Float.MIN_NORMAL, Float.MIN_NORMAL); assertEquals(Double.NaN, Float.NaN); } @Test void assertEqualsFloatWithUnequalValues() { try { assertEquals(1.0f, 1.1f); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0f, 1.1f); } } @Test void assertEqualsFloatWithUnequalValuesAndMessage() { try { assertEquals(1.0f, 1.1f, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0f, 1.1f); } } @Test void assertEqualsFloatWithUnequalValuesAndMessageSupplier() { try { assertEquals(1.0f, 1.1f, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0f, 1.1f); } } @Test void assertEqualsFloatWithDelta() { assertEquals(0.0f, 0.0f, 0.1f); assertEquals(0.0f, 0.0f, 0.1f, "message"); assertEquals(0.0f, 0.0f, 0.1f, () -> "message"); assertEquals(0.56f, 0.6f, 0.05f); assertEquals(0.01f, 0.011f, 0.002f); assertEquals(Float.NaN, Float.NaN, 0.5f); assertEquals(0.1f, 0.1f, 0.0f); } @Test void assertEqualsFloatWithIllegalDelta() { AssertionFailedError e1 = assertThrows(AssertionFailedError.class, () -> assertEquals(0.1f, 0.2f, -0.9f)); assertMessageEndsWith(e1, "positive delta expected but was: <-0.9>"); AssertionFailedError e2 = assertThrows(AssertionFailedError.class, () -> assertEquals(.0f, .0f, -10.5f)); assertMessageEndsWith(e2, "positive delta expected but was: <-10.5>"); AssertionFailedError e3 = assertThrows(AssertionFailedError.class, () -> assertEquals(4.5f, 4.6f, Float.NaN)); assertMessageEndsWith(e3, "positive delta expected but was: "); } @Test void assertEqualsFloatWithDeltaWithUnequalValues() { AssertionFailedError e1 = assertThrows(AssertionFailedError.class, () -> assertEquals(0.5f, 0.2f, 0.2f)); assertMessageEndsWith(e1, "expected: <0.5> but was: <0.2>"); AssertionFailedError e2 = assertThrows(AssertionFailedError.class, () -> assertEquals(0.1f, 0.2f, 0.000001f)); assertMessageEndsWith(e2, "expected: <0.1> but was: <0.2>"); AssertionFailedError e3 = assertThrows(AssertionFailedError.class, () -> assertEquals(100.0f, 50.0f, 10.0f)); assertMessageEndsWith(e3, "expected: <100.0> but was: <50.0>"); AssertionFailedError e4 = assertThrows(AssertionFailedError.class, () -> assertEquals(-3.5f, -3.3f, 0.01f)); assertMessageEndsWith(e4, "expected: <-3.5> but was: <-3.3>"); AssertionFailedError e5 = assertThrows(AssertionFailedError.class, () -> assertEquals(+0.0f, -0.001f, .00001f)); assertMessageEndsWith(e5, "expected: <0.0> but was: <-0.001>"); } @Test void assertEqualsFloatWithDeltaWithUnequalValuesAndMessage() { Executable assertion = () -> assertEquals(0.5f, 0.45f, 0.03f, "message"); AssertionFailedError e = assertThrows(AssertionFailedError.class, assertion); assertMessageStartsWith(e, "message"); assertMessageEndsWith(e, "expected: <0.5> but was: <0.45>"); assertExpectedAndActualValues(e, 0.5f, 0.45f); } @Test void assertEqualsFloatWithDeltaWithUnequalValuesAndMessageSupplier() { Executable assertion = () -> assertEquals(0.5f, 0.45f, 0.03f, () -> "message"); AssertionFailedError e = assertThrows(AssertionFailedError.class, assertion); assertMessageStartsWith(e, "message"); assertMessageEndsWith(e, "expected: <0.5> but was: <0.45>"); assertExpectedAndActualValues(e, 0.5f, 0.45f); } @Test void assertEqualsDouble() { assertEquals(1.0d, 1.0d); assertEquals(1.0d, 1.0d, "message"); assertEquals(1.0d, 1.0d, () -> "message"); assertEquals(Double.NaN, Double.NaN); assertEquals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); assertEquals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); assertEquals(Double.MIN_VALUE, Double.MIN_VALUE); assertEquals(Double.MAX_VALUE, Double.MAX_VALUE); assertEquals(Double.MIN_NORMAL, Double.MIN_NORMAL); } @Test void assertEqualsDoubleWithUnequalValues() { try { assertEquals(1.0d, 1.1d); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0d, 1.1d); } } @Test void assertEqualsDoubleWithUnequalValuesAndMessage() { try { assertEquals(1.0d, 1.1d, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0d, 1.1d); } } @Test void assertEqualsDoubleWithUnequalValuesAndMessageSupplier() { try { assertEquals(1.0d, 1.1d, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected: <1.0> but was: <1.1>"); assertExpectedAndActualValues(ex, 1.0d, 1.1d); } } @Test void assertEqualsDoubleWithDelta() { assertEquals(0.0d, 0.0d, 0.1d); assertEquals(0.0d, 0.0d, 0.1d, "message"); assertEquals(0.0d, 0.0d, 0.1d, () -> "message"); assertEquals(0.42d, 0.24d, 0.19d); assertEquals(0.02d, 0.011d, 0.01d); assertEquals(Double.NaN, Double.NaN, 0.2d); assertEquals(0.001d, 0.001d, 0.0d); } @Test void assertEqualsDoubleWithIllegalDelta() { AssertionFailedError e1 = assertThrows(AssertionFailedError.class, () -> assertEquals(1.1d, 1.11d, -0.5d)); assertMessageEndsWith(e1, "positive delta expected but was: <-0.5>"); AssertionFailedError e2 = assertThrows(AssertionFailedError.class, () -> assertEquals(.55d, .56d, -10.5d)); assertMessageEndsWith(e2, "positive delta expected but was: <-10.5>"); AssertionFailedError e3 = assertThrows(AssertionFailedError.class, () -> assertEquals(1.1d, 1.1d, Double.NaN)); assertMessageEndsWith(e3, "positive delta expected but was: "); } @Test void assertEqualsDoubleWithDeltaWithUnequalValues() { AssertionFailedError e1 = assertThrows(AssertionFailedError.class, () -> assertEquals(9.9d, 9.7d, 0.1d)); assertMessageEndsWith(e1, "expected: <9.9> but was: <9.7>"); assertExpectedAndActualValues(e1, 9.9d, 9.7d); AssertionFailedError e2 = assertThrows(AssertionFailedError.class, () -> assertEquals(0.1d, 0.05d, 0.001d)); assertMessageEndsWith(e2, "expected: <0.1> but was: <0.05>"); assertExpectedAndActualValues(e2, 0.1d, 0.05d); AssertionFailedError e3 = assertThrows(AssertionFailedError.class, () -> assertEquals(17.11d, 15.11d, 1.1d)); assertMessageEndsWith(e3, "expected: <17.11> but was: <15.11>"); assertExpectedAndActualValues(e3, 17.11d, 15.11d); AssertionFailedError e4 = assertThrows(AssertionFailedError.class, () -> assertEquals(-7.2d, -5.9d, 1.1d)); assertMessageEndsWith(e4, "expected: <-7.2> but was: <-5.9>"); assertExpectedAndActualValues(e4, -7.2d, -5.9d); AssertionFailedError e5 = assertThrows(AssertionFailedError.class, () -> assertEquals(+0.0d, -0.001d, .00001d)); assertMessageEndsWith(e5, "expected: <0.0> but was: <-0.001>"); assertExpectedAndActualValues(e5, +0.0d, -0.001d); } @Test void assertEqualsDoubleWithDeltaWithUnequalValuesAndMessage() { Executable assertion = () -> assertEquals(42.42d, 42.4d, 0.001d, "message"); AssertionFailedError e = assertThrows(AssertionFailedError.class, assertion); assertMessageStartsWith(e, "message"); assertMessageEndsWith(e, "expected: <42.42> but was: <42.4>"); assertExpectedAndActualValues(e, 42.42d, 42.4d); } @Test void assertEqualsDoubleWithDeltaWithUnequalValuesAndMessageSupplier() { Executable assertion = () -> assertEquals(0.9d, 10.12d, 5.001d, () -> "message"); AssertionFailedError e = assertThrows(AssertionFailedError.class, assertion); assertMessageStartsWith(e, "message"); assertMessageEndsWith(e, "expected: <0.9> but was: <10.12>"); assertExpectedAndActualValues(e, 0.9d, 10.12d); } @Test void assertEqualsWithNullReferences() { Object null1 = null; Object null2 = null; assertEquals(null1, null); assertEquals(null, null2); assertEquals(null1, null2); } @Test void assertEqualsWithSameObject() { Object foo = new Object(); assertEquals(foo, foo); assertEquals(foo, foo, "message"); assertEquals(foo, foo, () -> "message"); } @Test void assertEqualsWithEquivalentStrings() { assertEquals(new String("foo"), new String("foo")); } @Test void assertEqualsWithNullVsObject() { try { assertEquals(null, "foo"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, null, "foo"); } } @Test void assertEqualsWithObjectVsNull() { try { assertEquals("foo", null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, "foo", null); } } @Test void assertEqualsWithObjectWithNullStringReturnedFromToStringVsNull() { try { assertEquals("null", null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "expected: java.lang.String@"); assertMessageEndsWith(ex, " but was: "); assertExpectedAndActualValues(ex, "null", null); } } @Test void assertEqualsWithNullVsObjectWithNullStringReturnedFromToString() { try { assertEquals(null, "null"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "expected: but was: java.lang.String@"); assertMessageEndsWith(ex, ""); assertExpectedAndActualValues(ex, null, "null"); } } @Test void assertEqualsWithNullVsObjectAndMessageSupplier() { try { assertEquals(null, "foo", () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageEndsWith(ex, "expected: but was: "); assertExpectedAndActualValues(ex, null, "foo"); } } @Test void assertEqualsWithObjectVsNullAndMessageSupplier() { try { assertEquals("foo", null, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageEndsWith(ex, "expected: but was: "); assertExpectedAndActualValues(ex, "foo", null); } } @Test void assertEqualsInvokesEqualsMethodForIdenticalObjects() { Object obj = new EqualsThrowsException(); assertThrows(NumberFormatException.class, () -> assertEquals(obj, obj)); } @Test void assertEqualsWithUnequalObjectWhoseToStringImplementationThrowsAnException() { try { assertEquals(new ToStringThrowsException(), "foo"); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "expected: <" + ToStringThrowsException.class.getName() + "@"); assertMessageEndsWith(ex, "but was: "); } } // ------------------------------------------------------------------------- @Nested class MixedBoxedAndUnboxedPrimitivesTests { @Test void bytes() { byte primitive = (byte) 42; Byte wrapper = Byte.valueOf("42"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } @Test void shorts() { short primitive = (short) 42; Short wrapper = Short.valueOf("42"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } @Test void integers() { int primitive = 42; Integer wrapper = Integer.valueOf("42"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } @Test void longs() { long primitive = 42L; Long wrapper = Long.valueOf("42"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } @Test void floats() { float primitive = 42.0f; Float wrapper = Float.valueOf("42.0"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, 0.0f); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, 0.0f, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(primitive, wrapper, 0.0f, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, 0.0f); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, 0.0f, "message"); assertEquals(wrapper, primitive, () -> "message"); assertEquals(wrapper, primitive, 0.0f, () -> "message"); } @Test void doubles() { double primitive = 42.0d; Double wrapper = Double.valueOf("42.0"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, 0.0d); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, 0.0d, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(primitive, wrapper, 0.0d, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, 0.0d); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, 0.0d, "message"); assertEquals(wrapper, primitive, () -> "message"); assertEquals(wrapper, primitive, 0.0d, () -> "message"); } @Test void booleans() { boolean primitive = true; Boolean wrapper = Boolean.valueOf("true"); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } @Test void chars() { char primitive = 'a'; Character wrapper = Character.valueOf('a'); assertEquals(primitive, wrapper); assertEquals(primitive, wrapper, "message"); assertEquals(primitive, wrapper, () -> "message"); assertEquals(wrapper, primitive); assertEquals(wrapper, primitive, "message"); assertEquals(wrapper, primitive, () -> "message"); } } // ------------------------------------------------------------------------- private static class EqualsThrowsException { @Override public boolean equals(Object obj) { throw new NumberFormatException(); } } private static class ToStringThrowsException { @Override public String toString() { throw new NumberFormatException(); } } } AssertFalseAssertionsTests.java000066400000000000000000000055161455764576500342520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertExpectedAndActualValues; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertFalse; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertFalseAssertionsTests { @Test void assertFalseWithBooleanFalse() { assertFalse(false); assertFalse(false, "test"); assertFalse(false, () -> "test"); } @Test void assertFalseWithBooleanSupplierFalse() { assertFalse(() -> false); assertFalse(() -> false, "test"); assertFalse(() -> false, () -> "test"); } @Test void assertFalseWithBooleanFalseAndMessageSupplier() { assertFalse(false, () -> "test"); } @Test void assertFalseWithBooleanSupplierFalseAndMessageSupplier() { assertFalse(() -> false, () -> "test"); } @Test void assertFalseWithBooleanTrueAndDefaultMessageWithExpectedAndActualValues() { try { assertFalse(true); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, false, true); } } @Test void assertFalseWithBooleanTrueAndString() { try { assertFalse(true, "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, false, true); } } @Test void assertFalseWithBooleanSupplierTrueAndString() { try { assertFalse(() -> true, "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, false, true); } } @Test void assertFalseWithBooleanTrueAndMessageSupplier() { try { assertFalse(true, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, false, true); } } @Test void assertFalseWithBooleanSupplierTrueAndMessageSupplier() { try { assertFalse(() -> true, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, false, true); } } } AssertInstanceOfAssertionsTests.java000066400000000000000000000071161455764576500352470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import org.junit.jupiter.api.function.Executable; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions#assertInstanceOf(Class, Object)}. * * @since 5.8 */ class AssertInstanceOfAssertionsTests { @Test void assertInstanceOfFailsNullValue() { assertInstanceOfFails(String.class, null, "null value"); } @Test void assertInstanceOfFailsWrongTypeValue() { assertInstanceOfFails(String.class, 1, "type"); } @Test void assertInstanceOfFailsWrongExceptionValue() { assertInstanceOfFails(RuntimeException.class, new IOException(), "type"); } @Test void assertInstanceOfFailsSuperTypeExceptionValue() { assertInstanceOfFails(IllegalArgumentException.class, new RuntimeException(), "type"); } private static class BaseClass { } private static class SubClass extends BaseClass { } @Test void assertInstanceOfFailsSuperTypeValue() { assertInstanceOfFails(SubClass.class, new BaseClass(), "type"); } @Test void assertInstanceOfSucceedsSameTypeValue() { assertInstanceOfSucceeds(String.class, "indeed a String"); assertInstanceOfSucceeds(BaseClass.class, new BaseClass()); assertInstanceOfSucceeds(SubClass.class, new SubClass()); } @Test void assertInstanceOfSucceedsExpectSuperClassOfValue() { assertInstanceOfSucceeds(CharSequence.class, "indeed a CharSequence"); assertInstanceOfSucceeds(BaseClass.class, new SubClass()); } @Test void assertInstanceOfSucceedsSameTypeExceptionValue() { assertInstanceOfSucceeds(UnsupportedOperationException.class, new UnsupportedOperationException()); } @Test void assertInstanceOfSucceedsExpectSuperClassOfExceptionValue() { assertInstanceOfSucceeds(RuntimeException.class, new IllegalArgumentException("is a RuntimeException")); } private void assertInstanceOfSucceeds(Class expectedType, Object actualValue) { T res = assertInstanceOf(expectedType, actualValue); assertSame(res, actualValue); res = assertInstanceOf(expectedType, actualValue, "extra"); assertSame(res, actualValue); res = assertInstanceOf(expectedType, actualValue, () -> "extra"); assertSame(res, actualValue); } private void assertInstanceOfFails(Class expectedType, Object actualValue, String unexpectedSort) { String valueType = actualValue == null ? "null" : actualValue.getClass().getCanonicalName(); String expectedMessage = String.format("Unexpected %s, expected: <%s> but was: <%s>", unexpectedSort, expectedType.getCanonicalName(), valueType); assertThrowsWithMessage(expectedMessage, () -> assertInstanceOf(expectedType, actualValue)); assertThrowsWithMessage("extra ==> " + expectedMessage, () -> assertInstanceOf(expectedType, actualValue, "extra")); assertThrowsWithMessage("extra ==> " + expectedMessage, () -> assertInstanceOf(expectedType, actualValue, () -> "extra")); } private void assertThrowsWithMessage(String expectedMessage, Executable executable) { assertEquals(expectedMessage, assertThrows(AssertionFailedError.class, executable).getMessage()); } } AssertIterableEqualsAssertionsTests.java000066400000000000000000000410741455764576500361210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEndsWith; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.IterableFactory.listOf; import static org.junit.jupiter.api.IterableFactory.setOf; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertIterableEqualsAssertionsTests { @Test void assertIterableEqualsEqualToSelf() { List list = listOf("a", 'b', 1, 2); assertIterableEquals(list, list); assertIterableEquals(list, list, "message"); assertIterableEquals(list, list, () -> "message"); Set set = setOf("a", 'b', 1, 2); assertIterableEquals(set, set); } @Test void assertIterableEqualsEqualObjectsOfSameType() { assertIterableEquals(listOf(), listOf()); assertIterableEquals(listOf("abc"), listOf("abc")); assertIterableEquals(listOf("abc", 1, 2L, 3D), listOf("abc", 1, 2L, 3D)); assertIterableEquals(setOf(), setOf()); assertIterableEquals(setOf("abc"), setOf("abc")); assertIterableEquals(setOf("abc", 1, 2L, 3D), setOf("abc", 1, 2L, 3D)); } @Test void assertIterableEqualsNestedIterables() { assertIterableEquals(listOf(listOf(listOf())), listOf(listOf(listOf()))); assertIterableEquals(setOf(setOf(setOf())), setOf(setOf(setOf()))); } @Test void assertIterableEqualsNestedIterablesWithNull() { assertIterableEquals(listOf(null, listOf(null, listOf(null, null)), null, listOf((List) null)), listOf(null, listOf(null, listOf(null, null)), null, listOf((List) null))); assertIterableEquals(setOf(null, setOf(null, setOf(null, null)), null, setOf((Set) null)), setOf(null, setOf(null, setOf(null, null)), null, setOf((Set) null))); } @Test void assertIterableEqualsNestedIterablesWithStrings() { assertIterableEquals(listOf("a", listOf(listOf("b", listOf("c", "d"))), "e"), listOf("a", listOf(listOf("b", listOf("c", "d"))), "e")); assertIterableEquals(setOf("a", setOf(setOf("b", setOf("c", "d"))), "e"), setOf("a", setOf(setOf("b", setOf("c", "d"))), "e")); } @Test void assertIterableEqualsNestedIterablesWithIntegers() { assertIterableEquals(listOf(listOf(1), listOf(2), listOf(listOf(3, listOf(4)))), listOf(listOf(1), listOf(2), listOf(listOf(3, listOf(4))))); assertIterableEquals(setOf(setOf(1), setOf(2), setOf(setOf(3, setOf(4)))), setOf(setOf(1), setOf(2), setOf(setOf(3, setOf(4))))); assertIterableEquals(listOf(listOf(1), listOf(listOf(1))), setOf(setOf(1), setOf(setOf(1)))); } @Test void assertIterableEqualsNestedIterablesWithDeeplyNestedObject() { assertIterableEquals(listOf(listOf(listOf(listOf(listOf(listOf(listOf("abc"))))))), listOf(listOf(listOf(listOf(listOf(listOf(listOf("abc")))))))); assertIterableEquals(setOf(setOf(setOf(setOf(setOf(setOf(setOf("abc"))))))), setOf(setOf(setOf(setOf(setOf(setOf(setOf("abc")))))))); } @Test void assertIterableEqualsNestedIterablesWithNaN() { assertIterableEquals(listOf(null, listOf(null, Double.NaN, listOf(Float.NaN, null, listOf()))), listOf(null, listOf(null, Double.NaN, listOf(Float.NaN, null, listOf())))); assertIterableEquals(setOf(null, setOf(null, Double.NaN, setOf(Float.NaN, null, setOf()))), setOf(null, setOf(null, Double.NaN, setOf(Float.NaN, null, setOf())))); } @Test void assertIterableEqualsNestedIterablesWithObjectsOfDifferentTypes() { assertIterableEquals(listOf(new String("a"), Integer.valueOf(1), listOf(Double.parseDouble("1.1"), "b")), listOf(new String("a"), Integer.valueOf(1), listOf(Double.parseDouble("1.1"), "b"))); assertIterableEquals(setOf(new String("a"), Integer.valueOf(1), setOf(Double.parseDouble("1.1"), "b")), setOf(new String("a"), Integer.valueOf(1), setOf(Double.parseDouble("1.1"), "b"))); } @Test void assertIterableEqualsNestedIterablesOfMixedSubtypes() { assertIterableEquals( listOf(1, 2, listOf(3, setOf(4, 5), setOf(6L), listOf(listOf(setOf(7)))), setOf(8), listOf(setOf(9L))), listOf(1, 2, listOf(3, setOf(4, 5), setOf(6L), listOf(listOf(setOf(7)))), setOf(8), listOf(setOf(9L)))); assertIterableEquals( listOf("a", setOf('b', 'c'), setOf((int) 'd'), listOf(listOf(listOf("ef"), listOf(listOf("ghi"))))), setOf("a", listOf('b', 'c'), listOf((int) 'd'), setOf(setOf(setOf("ef"), setOf(setOf("ghi")))))); } @Test void assertIterableEqualsIterableVsNull() { try { assertIterableEquals(null, listOf("a", "b", 1, listOf())); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected iterable was "); } try { assertIterableEquals(listOf('a', 1, new Object(), 10L), null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual iterable was "); } } @Test void assertIterableEqualsNestedIterableVsNull() { try { assertIterableEquals(listOf(listOf(), 1, "2", setOf('3', listOf((List) null))), listOf(listOf(), 1, "2", setOf('3', listOf(listOf("4"))))); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected iterable was at index [3][1][0]"); } try { assertIterableEquals(setOf(1, 2, listOf(3, listOf("4", setOf(5, setOf(6)))), "7"), setOf(1, 2, listOf(3, listOf("4", setOf(5, null))), "7")); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "actual iterable was at index [2][1][1][1]"); } } @Test void assertIterableEqualsIterableVsNullAndMessage() { try { assertIterableEquals(null, listOf('a', "b", 10, 20D), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected iterable was "); } try { assertIterableEquals(listOf("hello", 42), null, "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual iterable was "); } } @Test void assertIterableEqualsNestedIterableVsNullAndMessage() { try { assertIterableEquals(listOf(1, listOf(2, 3, listOf(4, 5, listOf((List) null)))), listOf(1, listOf(2, 3, listOf(4, 5, listOf(listOf(6))))), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected iterable was at index [1][2][2][0]"); } try { assertIterableEquals(listOf(1, listOf(2, listOf(3, listOf(listOf(4))))), listOf(1, listOf(2, listOf(3, listOf((List) null)))), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual iterable was at index [1][1][1][0]"); } } @Test void assertIterableEqualsIterableVsNullAndMessageSupplier() { try { assertIterableEquals(null, setOf(42, "42", listOf(42F), 42D), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected iterable was "); } try { assertIterableEquals(listOf(listOf("a"), listOf()), null, () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual iterable was "); } } @Test void assertIterableEqualsNestedIterableVsNullAndMessageSupplier() { try { assertIterableEquals(listOf("1", "2", "3", listOf("4", listOf((List) null))), listOf("1", "2", "3", listOf("4", listOf(listOf(5)))), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "expected iterable was at index [3][1][0]"); } try { assertIterableEquals(setOf(1, 2, setOf("3", setOf('4', setOf(5, 6, setOf())))), setOf(1, 2, setOf("3", setOf('4', setOf(5, 6, null)))), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "actual iterable was at index [2][1][1][2]"); } } @Test void assertIterableEqualsIterablesOfDifferentLength() { try { assertIterableEquals(listOf('a', "b", 'c'), listOf('a', "b", 'c', 1)); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable lengths differ, expected: <3> but was: <4>"); } } @Test void assertIterableEqualsNestedIterablesOfDifferentLength() { try { assertIterableEquals(listOf("a", setOf("b", listOf("c", "d", setOf("e", 1, 2, 3)))), listOf("a", setOf("b", listOf("c", "d", setOf("e", 1, 2, 3, 4, 5))))); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable lengths differ at index [1][1][2], expected: <4> but was: <6>"); } try { assertIterableEquals(listOf(listOf(listOf(listOf(listOf(listOf(listOf('a'))))))), listOf(listOf(listOf(listOf(listOf(listOf(listOf('a', 'b')))))))); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable lengths differ at index [0][0][0][0][0][0], expected: <1> but was: <2>"); } } @Test void assertIterableEqualsIterablesOfDifferentLengthAndMessage() { try { assertIterableEquals(setOf('a', 1), setOf('a', 1, new Object()), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable lengths differ, expected: <2> but was: <3>"); } } @Test void assertIterableEqualsNestedIterablesOfDifferentLengthAndMessage() { try { assertIterableEquals(listOf('a', 1, listOf(2, 3)), listOf('a', 1, listOf(2, 3, 4, 5)), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable lengths differ at index [2], expected: <2> but was: <4>"); } } @Test void assertIterableEqualsIterablesOfDifferentLengthAndMessageSupplier() { try { assertIterableEquals(setOf("a", "b", "c"), setOf("a", "b", "c", "d", "e", "f"), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable lengths differ, expected: <3> but was: <6>"); } } @Test void assertIterableEqualsNestedIterablesOfDifferentLengthAndMessageSupplier() { try { assertIterableEquals(listOf("a", setOf(1, 2, 3, listOf(4.0, 5.1, 6.1), 7)), listOf("a", setOf(1, 2, 3, listOf(4.0, 5.1, 6.1, 7.0), 8)), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable lengths differ at index [1][3], expected: <3> but was: <4>"); } } @Test void assertIterableEqualsDifferentIterables() { try { assertIterableEquals(listOf(1L, "2", '3', 4, 5D), listOf(1L, "2", '9', 4, 5D)); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable contents differ at index [2], expected: <3> but was: <9>"); } try { assertIterableEquals(listOf("a", 10, 11, 12, Double.NaN), listOf("a", 10, 11, 12, 13.55D)); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable contents differ at index [4], expected: but was: <13.55>"); } } @Test void assertIterableEqualsDifferentNestedIterables() { try { assertIterableEquals(listOf(1, 2, listOf(3, listOf(4, listOf(false, true)))), listOf(1, 2, listOf(3, listOf(4, listOf(true, false))))); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable contents differ at index [2][1][1][0], expected: but was: "); } List differentElement = listOf(); try { assertIterableEquals(listOf(1, 2, 3, listOf(listOf(4, listOf(5)))), listOf(1, 2, 3, listOf(listOf(4, listOf(differentElement))))); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable contents differ at index [3][0][1][0], expected: <5> but was: <" + differentElement + ">"); } } @Test void assertIterableEqualsDifferentIterablesAndMessage() { try { assertIterableEquals(listOf(1.1D, 2L, "3"), listOf(1D, 2L, "3"), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [0], expected: <1.1> but was: <1.0>"); } } @Test void assertIterableEqualsDifferentNestedIterablesAndMessage() { try { assertIterableEquals(listOf(9, 8, '6', listOf(5, 4, "3", listOf("2", '1'))), listOf(9, 8, '6', listOf(5, 4, "3", listOf("99", '1'))), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [3][3][0], expected: <2> but was: <99>"); } try { assertIterableEquals(listOf(9, 8, '6', listOf(5, 4, "3", listOf("2", "1"))), listOf(9, 8, '6', listOf(5, 4, "3", listOf("99", "1"))), "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [3][3][0], expected: <2> but was: <99>"); } } @Test void assertIterableEqualsDifferentIterablesAndMessageSupplier() { try { assertIterableEquals(setOf("one", 1L, Double.MIN_VALUE, "abc"), setOf("one", 1L, 42.42, "abc"), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [2], expected: <4.9E-324> but was: <42.42>"); } } @Test void assertIterableEqualsDifferentNestedIterablesAndMessageSupplier() { try { assertIterableEquals(setOf("one", 1L, setOf("a", 'b', setOf(1, setOf(2, 3))), "abc"), setOf("one", 1L, setOf("a", 'b', setOf(1, setOf(2, 4))), "abc"), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [2][2][1][1], expected: <3> but was: <4>"); } try { assertIterableEquals(listOf("j", listOf("a"), setOf(42), "ab", setOf(1, listOf(3))), listOf("j", listOf("a"), setOf(42), "ab", setOf(1, listOf(5))), () -> "message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "message"); assertMessageEndsWith(ex, "iterable contents differ at index [4][1][0], expected: <3> but was: <5>"); } } @Test // https://github.com/junit-team/junit5/issues/2157 void assertIterableEqualsWithListOfPath() { var expected = listOf(Path.of("1")); var actual = listOf(Path.of("1")); assertDoesNotThrow(() -> assertIterableEquals(expected, actual)); } @Test void assertIterableEqualsThrowsStackOverflowErrorForInterlockedRecursiveStructures() { var expected = new ArrayList<>(); var actual = new ArrayList<>(); actual.add(expected); expected.add(actual); assertThrows(StackOverflowError.class, () -> assertIterableEquals(expected, actual)); } @Test // https://github.com/junit-team/junit5/issues/2915 void assertIterableEqualsWithDifferentListOfPath() { try { var expected = listOf(Path.of("1").resolve("2")); var actual = listOf(Path.of("1").resolve("3")); assertIterableEquals(expected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "iterable contents differ at index [0][1], expected: <2> but was: <3>"); } } } AssertLinesMatchAssertionsTests.java000066400000000000000000000331131455764576500352410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertLinesMatch.isFastForwardLine; import static org.junit.jupiter.api.AssertLinesMatch.parseFastForwardLimit; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.platform.commons.PreconditionViolationException; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertLinesMatchAssertionsTests { @Test void assertLinesMatchEmptyLists() { assertLinesMatch(Collections.emptyList(), new ArrayList<>()); } @Test void assertLinesMatchSameListInstance() { List list = List.of("first line", "second line", "third line", "last line"); assertLinesMatch(list, list); } @Test void assertLinesMatchPlainEqualLists() { List expected = List.of("first line", "second line", "third line", "last line"); List actual = List.of("first line", "second line", "third line", "last line"); assertLinesMatch(expected, actual); } @Test void assertLinesMatchUsingRegexPatterns() { List expected = List.of("^first.+line", "second\\s*line", "th.rd l.ne", "last line$"); List actual = List.of("first line", "second line", "third line", "last line"); assertLinesMatch(expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerAtEndOfExpectedLines() { List expected = List.of("first line", ">> ignore all following lines >>"); List actual = List.of("first line", "I", "II", "III", "IV", "V", "VI", "last line"); assertLinesMatch(expected, actual); } @Test void assertLinesMatchUsingFastForwardMarker() { List expected = List.of("first line", ">> skip lines until next matches >>", "V", "last line"); List actual = List.of("first line", "I", "II", "III", "IV", "V", "last line"); assertLinesMatch(expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithLimit1() { List expected = List.of("first line", ">> 1 >>", "last line"); List actual = List.of("first line", "skipped", "last line"); assertLinesMatch(expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithLimit3() { List expected = Collections.singletonList(">> 3 >>"); List actual = List.of("first line", "skipped", "last line"); assertLinesMatch(expected, actual); } @Test @SuppressWarnings({ "unchecked", "rawtypes" }) void assertLinesMatchWithNullFails() { assertThrows(PreconditionViolationException.class, () -> assertLinesMatch((List) null, (List) null)); assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(null, Collections.emptyList())); assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(Collections.emptyList(), null)); } @Test void assertLinesMatchWithNullElementsFails() { var list = List.of("1", "2", "3"); var withNullElement = Arrays.asList("1", null, "3"); // List.of() doesn't permit null values. assertDoesNotThrow(() -> assertLinesMatch(withNullElement, withNullElement)); var e1 = assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(withNullElement, list)); assertEquals("expected line must not be null", e1.getMessage()); var e2 = assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(list, withNullElement)); assertEquals("actual line must not be null", e2.getMessage()); } private void assertError(AssertionFailedError error, String expectedMessage, List expectedLines, List actualLines) { assertEquals(expectedMessage, error.getMessage()); assertEquals(String.join(System.lineSeparator(), expectedLines), error.getExpected().getStringRepresentation()); assertEquals(String.join(System.lineSeparator(), actualLines), error.getActual().getStringRepresentation()); } @Test void assertLinesMatchMoreExpectedThanActualAvailableFails() { var expected = List.of("first line", "second line", "third line"); var actual = List.of("first line", "third line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "expected 3 lines, but only got 2", expected, actual); } @Test void assertLinesMatchFailsWithDescriptiveErrorMessage() { var expected = List.of("first line", "second line", "third line"); var actual = List.of("first line", "sec0nd line", "third line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); var expectedMessage = String.join(System.lineSeparator(), List.of( // "expected line #2 doesn't match actual line #2", // "\texpected: `second line`", // "\t actual: `sec0nd line`")); assertError(error, expectedMessage, expected, actual); } @Test void assertLinesMatchMoreActualLinesThenExpectedFails() { var expected = List.of("first line", "second line", "third line"); var actual = List.of("first line", "second line", "third line", "last line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "more actual lines than expected: 1", expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithTooLowLimitFails() { var expected = List.of("first line", ">> 1 >>"); var actual = List.of("first line", "skipped", "last line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "terminal fast-forward(1) error: fast-forward(2) expected", expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithTooHighLimitFails() { var expected = List.of("first line", ">> 100 >>"); var actual = List.of("first line", "skipped", "last line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "terminal fast-forward(100) error: fast-forward(2) expected", expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithTooHighLimitAndFollowingLineFails() { /* * It is important here that the line counts are expected <= actual, that the * fast-forward exceeds the available actual lines and that it is not a * terminal fast-forward. */ var expected = List.of("first line", ">> 3 >>", "not present"); var actual = List.of("first line", "first skipped", "second skipped"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "fast-forward(3) error: not enough actual lines remaining (2)", expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithoutMatchingNextLineFails() { var expected = List.of("first line", ">> fails, because next line is >>", "not present"); var actual = List.of("first line", "skipped", "last line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "fast-forward(∞) didn't find: `not present`", expected, actual); } @Test void assertLinesMatchUsingFastForwardMarkerWithExtraExpectLineFails() { var expected = List.of("first line", ">> fails, because final line is missing >>", "last line", "not present"); var actual = List.of("first line", "first skipped", "second skipped", "last line"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual)); assertError(error, "expected line #4:`not present` not found - actual lines depleted", expected, actual); } @Test void assertLinesMatchIsFastForwardLine() { assertAll("valid fast-forward lines", // () -> assertTrue(isFastForwardLine(">>>>")), () -> assertTrue(isFastForwardLine(">> >>")), () -> assertTrue(isFastForwardLine(">> stacktrace >>")), () -> assertTrue(isFastForwardLine(">> single line, non Integer.parse()-able comment >>")), () -> assertTrue(isFastForwardLine(">>9>>")), () -> assertTrue(isFastForwardLine(">> 9 >>")), () -> assertTrue(isFastForwardLine(">> -9 >>")), () -> assertTrue(isFastForwardLine(" >> 9 >> ")), () -> assertTrue(isFastForwardLine(" >> 9 >> "))); } @Test void assertLinesMatchParseFastForwardLimit() { assertAll("valid fast-forward limits", // () -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">>>>")), () -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> >>")), () -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> stacktrace >>")), () -> assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(">> non Integer.parse()-able comment >>")), () -> assertEquals(9, parseFastForwardLimit(">>9>>")), () -> assertEquals(9, parseFastForwardLimit(">> 9 >>")), () -> assertEquals(9, parseFastForwardLimit(" >> 9 >> ")), () -> assertEquals(9, parseFastForwardLimit(" >> 9 >> "))); Throwable error = assertThrows(PreconditionViolationException.class, () -> parseFastForwardLimit(">>0>>")); assertMessageEquals(error, "fast-forward(0) limit must be greater than zero"); error = assertThrows(PreconditionViolationException.class, () -> parseFastForwardLimit(">>-1>>")); assertMessageEquals(error, "fast-forward(-1) limit must be greater than zero"); error = assertThrows(PreconditionViolationException.class, () -> parseFastForwardLimit(">>-2147483648>>")); assertMessageEquals(error, "fast-forward(-2147483648) limit must be greater than zero"); } @Test void assertLinesMatchMatches() { Random random = new Random(); assertAll("do match", // () -> assertTrue( AssertLinesMatch.matches("duration: [\\d]+ ms", "duration: " + random.nextInt(1000) + " ms")), () -> assertTrue(AssertLinesMatch.matches("123", "123")), () -> assertTrue(AssertLinesMatch.matches(".*", "123")), () -> assertTrue(AssertLinesMatch.matches("\\d+", "123"))); assertAll("don't match", // () -> assertFalse( AssertLinesMatch.matches("duration: [\\d]+ ms", "duration: " + random.nextGaussian() + " ms")), () -> assertFalse(AssertLinesMatch.matches("12", "123")), () -> assertFalse(AssertLinesMatch.matches("..+", "1")), () -> assertFalse(AssertLinesMatch.matches("\\d\\d+", "1"))); } @Test void largeListsThatDoNotMatchAreTruncated() { var expected = IntStream.range(1, 999).boxed().map(Object::toString).collect(Collectors.toList()); var actual = IntStream.range(0, 1000).boxed().map(Object::toString).collect(Collectors.toList()); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual, "custom message")); var expectedMessage = String.join(System.lineSeparator(), List.of( // "custom message ==> expected line #1 doesn't match actual line #1", // "\texpected: `1`", // "\t actual: `0`")); assertError(error, expectedMessage, expected, actual); } /** * @since 5.5 */ @Nested class WithCustomFailureMessage { @Test void simpleStringMessage() { String message = "XXX"; var expected = List.of("a", "b", "c"); var actual = List.of("a", "d", "c"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual, message)); var expectedMessage = String.join(System.lineSeparator(), List.of( // message + " ==> expected line #2 doesn't match actual line #2", // "\texpected: `b`", // "\t actual: `d`")); assertError(error, expectedMessage, expected, actual); } @Test void stringSupplierWithMultiLineMessage() { var message = "XXX\nYYY"; Supplier supplier = () -> message; var expected = List.of("a", "b", "c"); var actual = List.of("a", "d", "c"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual, supplier)); var expectedMessage = String.join(System.lineSeparator(), List.of( // message + " ==> expected line #2 doesn't match actual line #2", // "\texpected: `b`", // "\t actual: `d`")); assertError(error, expectedMessage, expected, actual); } } @Nested class WithStreamsOfStrings { @Test void assertLinesMatchEmptyStreams() { assertLinesMatch(Stream.empty(), Stream.empty()); } @Test void assertLinesMatchSameListInstance() { Stream stream = Stream.of("first line", "second line", "third line", "last line"); assertLinesMatch(stream, stream); } @Test void assertLinesMatchPlainEqualLists() { var expected = """ first line second line third line last line """; var actual = """ first line second line third line last line """; assertLinesMatch(expected.lines(), actual.lines()); } @Test void assertLinesMatchUsingRegexPatterns() { var expected = """ ^first.+line second\\s*line th.rd l.ne last line$ """; var actual = """ first line second line third line last line """; assertLinesMatch(expected.lines(), actual.lines()); } } } AssertNotEqualsAssertionsTests.java000066400000000000000000000470331455764576500351330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEndsWith; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertNotEqualsAssertionsTests { @Nested class AssertNotEqualsByte { @Test void assertNotEqualsByte() { byte unexpected = 1; byte actual = 2; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void withEqualValues() { byte unexpected = 1; byte actual = 1; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessage() { byte unexpected = 1; byte actual = 1; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessageSupplier() { byte unexpected = 1; byte actual = 1; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } } @Nested class AssertNotEqualsShort { @Test void assertNotEqualsShort() { short unexpected = 1; short actual = 2; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void withEqualValues() { short unexpected = 1; short actual = 1; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessage() { short unexpected = 1; short actual = 1; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessageSupplier() { short unexpected = 1; short actual = 1; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } } @Nested class AssertNotEqualsChar { @Test void assertNotEqualsChar() { char unexpected = 'a'; char actual = 'b'; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void withEqualValues() { char unexpected = 'a'; char actual = 'a'; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: "); } } @Test void withEqualValuesWithMessage() { char unexpected = 'a'; char actual = 'a'; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: "); } } @Test void withEqualValuesWithMessageSupplier() { char unexpected = 'a'; char actual = 'a'; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: "); } } } @Nested class AssertNotEqualsInt { @Test void assertNotEqualsInt() { int unexpected = 1; int actual = 2; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void withEqualValues() { int unexpected = 1; int actual = 1; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessage() { int unexpected = 1; int actual = 1; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessageSupplier() { int unexpected = 1; int actual = 1; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } } @Nested class AssertNotEqualsLong { @Test void assertNotEqualsLong() { long unexpected = 1L; long actual = 2L; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void withEqualValues() { long unexpected = 1L; long actual = 1L; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessage() { long unexpected = 1L; long actual = 1L; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } @Test void withEqualValuesWithMessageSupplier() { long unexpected = 1L; long actual = 1L; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1>"); } } } @Nested class AssertNotEqualsFloatWithoutDelta { @Test void assertNotEqualsFloat() { float unexpected = 1.0f; float actual = 2.0f; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void assertNotEqualsForTwoNaNFloat() { try { assertNotEquals(Float.NaN, Float.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: "); } } @Test void assertNotEqualsForPositiveInfinityFloat() { try { assertNotEquals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: "); } } @Test void assertNotEqualsForNegativeInfinityFloat() { try { assertNotEquals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <-Infinity>"); } } @Test void withEqualValues() { float unexpected = 1.0f; float actual = 1.0f; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1.0>"); } } @Test void withEqualValuesWithMessage() { float unexpected = 1.0f; float actual = 1.0f; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1.0>"); } } @Test void withEqualValuesWithMessageSupplier() { float unexpected = 1.0f; float actual = 1.0f; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1.0>"); } } } @Nested class AssertNotEqualsFloatWithDelta { @Test void assertNotEqualsFloat() { assertNotEquals(1.0f, 1.5f, 0.4f); assertNotEquals(1.0f, 1.5f, 0.4f, "message"); assertNotEquals(1.0f, 1.5f, 0.4f, () -> "message"); } @Test void withEqualValues() { float unexpected = 1.0f; float actual = 1.5f; float delta = 0.5f; try { assertNotEquals(unexpected, actual, delta); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1.5>"); } } @Test void withEqualValuesWithMessage() { float unexpected = 1.0f; float actual = 1.5f; float delta = 0.5f; try { assertNotEquals(unexpected, actual, delta, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1.5>"); } } @Test void withEqualValuesWithMessageSupplier() { float unexpected = 1.0f; float actual = 1.5f; float delta = 0.5f; try { assertNotEquals(unexpected, actual, delta, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1.5>"); } } } @Nested class AssertNotEqualsDoubleWithoutDelta { @Test void assertNotEqualsDouble() { double unexpected = 1.0d; double actual = 2.0d; assertNotEquals(unexpected, actual); assertNotEquals(unexpected, actual, "message"); assertNotEquals(unexpected, actual, () -> "message"); } @Test void assertNotEqualsForTwoNaNDouble() { try { assertNotEquals(Double.NaN, Double.NaN); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: "); } } @Test void withEqualValues() { double unexpected = 1.0d; double actual = 1.0d; try { assertNotEquals(unexpected, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1.0>"); } } @Test void withEqualValuesWithMessage() { double unexpected = 1.0d; double actual = 1.0d; try { assertNotEquals(unexpected, actual, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1.0>"); } } @Test void withEqualValuesWithMessageSupplier() { double unexpected = 1.0d; double actual = 1.0d; try { assertNotEquals(unexpected, actual, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1.0>"); } } } @Nested class AssertNotEqualsDoubleWithDelta { @Test void assertNotEqualsDouble() { assertNotEquals(1.0d, 1.5d, 0.4d); assertNotEquals(1.0d, 1.5d, 0.4d, "message"); assertNotEquals(1.0d, 1.5d, 0.4d, () -> "message"); } @Test void withEqualValues() { double unexpected = 1.0d; double actual = 1.5d; double delta = 0.5d; try { assertNotEquals(unexpected, actual, delta); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not equal but was: <1.5>"); } } @Test void withEqualValuesWithMessage() { double unexpected = 1.0d; double actual = 1.5d; double delta = 0.5d; try { assertNotEquals(unexpected, actual, delta, "custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message"); assertMessageEndsWith(ex, "expected: not equal but was: <1.5>"); } } @Test void withEqualValuesWithMessageSupplier() { double unexpected = 1.0d; double actual = 1.5d; double delta = 0.5d; try { assertNotEquals(unexpected, actual, delta, () -> "custom message from supplier"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "custom message from supplier"); assertMessageEndsWith(ex, "expected: not equal but was: <1.5>"); } } } @Nested class AssertNotEqualsObject { @Test void assertNotEqualsWithNullVsObject() { assertNotEquals(null, "foo"); } @Test void assertNotEqualsWithObjectVsNull() { assertNotEquals("foo", null); } @Test void assertNotEqualsWithDifferentObjects() { assertNotEquals(new Object(), new Object()); assertNotEquals(new Object(), new Object(), "message"); assertNotEquals(new Object(), new Object(), () -> "message"); } @Test void assertNotEqualsWithNullVsObjectAndMessageSupplier() { assertNotEquals(null, "foo", () -> "test"); } @Test void assertNotEqualsWithEquivalentStringsAndMessage() { try { assertNotEquals(new String("foo"), new String("foo"), "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageEndsWith(ex, "expected: not equal but was: "); } } @Test void assertNotEqualsWithEquivalentStringsAndMessageSupplier() { try { assertNotEquals(new String("foo"), new String("foo"), () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageEndsWith(ex, "expected: not equal but was: "); } } @Test void assertNotEqualsInvokesEqualsMethodForIdenticalObjects() { Object obj = new EqualsThrowsExceptionClass(); assertThrows(NumberFormatException.class, () -> assertNotEquals(obj, obj)); } } // ------------------------------------------------------------------------- @Nested class MixedBoxedAndUnboxedPrimitivesTests { @Test void bytes() { byte primitive = (byte) 42; Byte wrapper = Byte.valueOf("99"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } @Test void shorts() { short primitive = (short) 42; Short wrapper = Short.valueOf("99"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } @Test void integers() { int primitive = 42; Integer wrapper = Integer.valueOf("99"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } @Test void longs() { long primitive = 42L; Long wrapper = Long.valueOf("99"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } @Test void floats() { float primitive = 42.0f; Float wrapper = Float.valueOf("99.0"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, 0.0f); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, 0.0f, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(primitive, wrapper, 0.0f, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, 0.0f); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, 0.0f, "message"); assertNotEquals(wrapper, primitive, () -> "message"); assertNotEquals(wrapper, primitive, 0.0f, () -> "message"); } @Test void doubles() { double primitive = 42.0d; Double wrapper = Double.valueOf("99.0"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, 0.0d); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, 0.0d, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(primitive, wrapper, 0.0d, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, 0.0d); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, 0.0d, "message"); assertNotEquals(wrapper, primitive, () -> "message"); assertNotEquals(wrapper, primitive, 0.0d, () -> "message"); } @Test void booleans() { boolean primitive = true; Boolean wrapper = Boolean.valueOf("false"); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } @Test void chars() { char primitive = 'a'; Character wrapper = Character.valueOf('z'); assertNotEquals(primitive, wrapper); assertNotEquals(primitive, wrapper, "message"); assertNotEquals(primitive, wrapper, () -> "message"); assertNotEquals(wrapper, primitive); assertNotEquals(wrapper, primitive, "message"); assertNotEquals(wrapper, primitive, () -> "message"); } } // ------------------------------------------------------------------------- private static class EqualsThrowsExceptionClass { @Override public boolean equals(Object obj) { throw new NumberFormatException(); } } } AssertNotNullAssertionsTests.java000066400000000000000000000032441455764576500346070ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEndsWith; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertNotNullAssertionsTests { @Test void assertNotNullWithNonNullObject() { assertNotNull("foo"); assertNotNull("foo", "message"); assertNotNull("foo", () -> "message"); } @Test void assertNotNullWithNonNullObjectAndMessageSupplier() { assertNotNull("foo", () -> "should not fail"); } @Test @SuppressWarnings("unused") void assertNotNullWithNull() { try { assertNotNull(null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not "); } } @Test @SuppressWarnings("unused") void assertNotNullWithNullAndMessageSupplier() { try { assertNotNull(null, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageEndsWith(ex, "expected: not "); } } } AssertNotSameAssertionsTests.java000066400000000000000000000044301455764576500345600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageContains; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertNotSame; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertNotSameAssertionsTests { @Test void assertNotSameWithDifferentObjects() { assertNotSame(new Object(), new Object()); assertNotSame(new Object(), new Object(), "message"); assertNotSame(new Object(), new Object(), () -> "message"); } @Test void assertNotSameWithDifferentObjectsAndMessageSupplier() { assertNotSame(new Object(), new Object(), () -> "should not fail"); } @Test void assertNotSameWithObjectVsNull() { assertNotSame(new Object(), null); } @Test void assertNotSameWithNullVsObject() { assertNotSame(null, new Object()); } @Test void assertNotSameWithTwoNulls() { try { assertNotSame(null, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: not same but was: "); } } @Test void assertNotSameWithSameObjectAndMessage() { try { Object foo = new Object(); assertNotSame(foo, foo, "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageContains(ex, "expected: not same but was: "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageContains(ex, "expected: not same but was: "message"); } @Test void assertNullWithNullAndMessageSupplier() { assertNull(null, () -> "test"); } @Test @SuppressWarnings("unused") void assertNullWithNonNullObject() { try { assertNull("foo"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, null, "foo"); } } @Test void assertNullWithNonNullObjectWithNullStringReturnedFromToString() { assertNullWithNonNullObjectWithNullStringReturnedFromToString(null); } @Test void assertNullWithNonNullObjectWithNullStringReturnedFromToStringAndMessageSupplier() { assertNullWithNonNullObjectWithNullStringReturnedFromToString(() -> "boom"); } @SuppressWarnings("unused") private void assertNullWithNonNullObjectWithNullStringReturnedFromToString(Supplier messageSupplier) { String actual = "null"; try { if (messageSupplier == null) { assertNull(actual); } else { assertNull(actual, messageSupplier); } expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like: // expected: but was: java.lang.String@264b3504 String prefix = (messageSupplier != null ? messageSupplier.get() + " ==> " : ""); assertMessageMatches(ex, prefix + "expected: but was: java\\.lang\\.String@.+"); assertExpectedAndActualValues(ex, null, actual); } } @Test void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString() { assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(null); } @Test void assertNullWithNonNullObjectWithNullReferenceReturnedFromToStringAndMessageSupplier() { assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(() -> "boom"); } @SuppressWarnings("unused") private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(Supplier messageSupplier) { Object actual = new NullToString(); try { if (messageSupplier == null) { assertNull(actual); } else { assertNull(actual, messageSupplier); } expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like: // expected: but was: org.junit.jupiter.api.AssertNullAssertionsTests$NullToString@4e7912d8 String prefix = (messageSupplier != null ? messageSupplier.get() + " ==> " : ""); assertMessageMatches(ex, prefix + "expected: but was: org\\.junit\\.jupiter\\.api\\.AssertNullAssertionsTests\\$NullToString@.+"); assertExpectedAndActualValues(ex, null, actual); } } @Test @SuppressWarnings("unused") void assertNullWithNonNullObjectAndMessage() { try { assertNull("foo", "a message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "a message ==> expected: but was: "); assertExpectedAndActualValues(ex, null, "foo"); } } @Test @SuppressWarnings("unused") void assertNullWithNonNullObjectAndMessageSupplier() { try { assertNull("foo", () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, null, "foo"); } } private static class NullToString { @Override public String toString() { return null; } } } AssertSameAssertionsTests.java000066400000000000000000000062771455764576500341120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertExpectedAndActualValues; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageContains; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageMatches; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertSame; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertSameAssertionsTests { @Test void assertSameWithTwoNulls() { assertSame(null, null); assertSame(null, null, () -> "should not fail"); } @Test void assertSameWithSameObject() { Object foo = new Object(); assertSame(foo, foo); assertSame(foo, foo, "message"); assertSame(foo, foo, () -> "message"); } @Test void assertSameWithObjectVsNull() { Object expected = new Object(); try { assertSame(expected, null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageContains(ex, "expected: "); assertExpectedAndActualValues(ex, expected, null); } } @Test void assertSameWithNullVsObject() { Object actual = new Object(); try { assertSame(null, actual); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: but was: java\\.lang\\.Integer@.+?<999>"); assertExpectedAndActualValues(ex, 999, 999); } } @Test void assertSameWithEquivalentStringsAndMessageSupplier() { String expected = new String("foo"); String actual = new String("foo"); try { assertSame(expected, actual, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "test"); assertMessageContains(ex, "expected: java.lang.String@"); assertMessageContains(ex, "but was: java.lang.String@"); assertExpectedAndActualValues(ex, expected, actual); } } } AssertThrowsAssertionsTests.java000066400000000000000000000232311455764576500345000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageContains; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.io.Serial; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.test.TestClassLoader; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ @SuppressWarnings("ExcessiveLambdaUsage") class AssertThrowsAssertionsTests { private static final Executable nix = () -> { }; @Test void assertThrowsWithMethodReferenceForNonVoidReturnType() { FutureTask future = new FutureTask<>(() -> { throw new RuntimeException("boom"); }); future.run(); ExecutionException exception = assertThrows(ExecutionException.class, future::get); assertEquals("boom", exception.getCause().getMessage()); } @Test void assertThrowsWithMethodReferenceForVoidReturnType() { var object = new Object(); IllegalMonitorStateException exception; exception = assertThrows(IllegalMonitorStateException.class, object::notify); assertNotNull(exception); // Note that Object.wait(...) is an overloaded method with a void return type exception = assertThrows(IllegalMonitorStateException.class, object::wait); assertNotNull(exception); } @Test void assertThrowsWithExecutableThatThrowsThrowable() { EnigmaThrowable enigmaThrowable = assertThrows(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsThrowableWithMessage() { EnigmaThrowable enigmaThrowable = assertThrows(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }, "message"); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsThrowableWithMessageSupplier() { EnigmaThrowable enigmaThrowable = assertThrows(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }, () -> "message"); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsCheckedException() { IOException exception = assertThrows(IOException.class, () -> { throw new IOException(); }); assertNotNull(exception); } @Test void assertThrowsWithExecutableThatThrowsRuntimeException() { IllegalStateException illegalStateException = assertThrows(IllegalStateException.class, () -> { throw new IllegalStateException(); }); assertNotNull(illegalStateException); } @Test void assertThrowsWithExecutableThatThrowsError() { StackOverflowError stackOverflowError = assertThrows(StackOverflowError.class, AssertionTestUtils::recurseIndefinitely); assertNotNull(stackOverflowError); } @Test void assertThrowsWithExecutableThatDoesNotThrowAnException() { try { assertThrows(IllegalStateException.class, nix); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Expected java.lang.IllegalStateException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatDoesNotThrowAnExceptionWithMessageString() { try { assertThrows(IOException.class, nix, "Custom message"); expectAssertionFailedError(); } catch (AssertionError ex) { assertMessageEquals(ex, "Custom message ==> Expected java.io.IOException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatDoesNotThrowAnExceptionWithMessageSupplier() { try { assertThrows(IOException.class, nix, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionError ex) { assertMessageEquals(ex, "Custom message ==> Expected java.io.IOException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedException() { try { assertThrows(IllegalStateException.class, () -> { throw new NumberFormatException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageString() { try { assertThrows(IllegalStateException.class, () -> { throw new NumberFormatException(); }, "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like this: // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageSupplier() { try { assertThrows(IllegalStateException.class, () -> { throw new NumberFormatException(); }, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like this: // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseInstanceOf(NumberFormatException.class); } } @Test @SuppressWarnings("serial") void assertThrowsWithExecutableThatThrowsInstanceOfAnonymousInnerClassAsUnexpectedException() { try { assertThrows(IllegalStateException.class, () -> { throw new NumberFormatException() { }; }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // As of the time of this writing, the class name of the above anonymous inner // class is org.junit.jupiter.api.AssertionsAssertThrowsTests$2; however, hard // coding "$2" is fragile. So we just check for the presence of the "$" // appended to this class's name. assertMessageContains(ex, "but was: <" + getClass().getName() + "$"); assertThat(ex).hasCauseInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsInstanceOfStaticNestedClassAsUnexpectedException() { try { assertThrows(IllegalStateException.class, () -> { throw new LocalException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // The following verifies that the canonical name is used (i.e., "." instead of "$"). assertMessageContains(ex, "but was: <" + LocalException.class.getName().replace("$", ".") + ">"); assertThat(ex).hasCauseInstanceOf(LocalException.class); } } @Test @SuppressWarnings("unchecked") void assertThrowsWithExecutableThatThrowsSameExceptionTypeFromDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(EnigmaThrowable.class)) { // Load expected exception type from different class loader Class enigmaThrowableClass = (Class) testClassLoader.loadClass( EnigmaThrowable.class.getName()); try { assertThrows(enigmaThrowableClass, () -> { throw new EnigmaThrowable(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Example Output: // // Unexpected exception type thrown, // expected: // but was: assertMessageStartsWith(ex, "Unexpected exception type thrown, "); // The presence of the "@" sign is sufficient to indicate that the hash was // generated to disambiguate between the two identical class names. assertMessageContains(ex, "expected: { }; @Test void assertThrowsExactlyTheSpecifiedExceptionClass() { var actual = assertThrowsExactly(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }); assertNotNull(actual); } @Test void assertThrowsExactlyWithTheExpectedChildException() { try { assertThrowsExactly(RuntimeException.class, () -> { throw new Exception(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseExactlyInstanceOf(Exception.class); } } @Test void assertThrowsExactlyWithTheExpectedParentException() { try { assertThrowsExactly(RuntimeException.class, () -> { throw new NumberFormatException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseExactlyInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithMethodReferenceForNonVoidReturnType() { FutureTask future = new FutureTask<>(() -> { throw new RuntimeException("boom"); }); future.run(); ExecutionException exception = assertThrowsExactly(ExecutionException.class, future::get); assertEquals("boom", exception.getCause().getMessage()); } @Test void assertThrowsWithMethodReferenceForVoidReturnType() { var object = new Object(); IllegalMonitorStateException exception; exception = assertThrowsExactly(IllegalMonitorStateException.class, object::notify); assertNotNull(exception); // Note that Object.wait(...) is an overloaded method with a void return type exception = assertThrowsExactly(IllegalMonitorStateException.class, object::wait); assertNotNull(exception); } @Test void assertThrowsWithExecutableThatThrowsThrowable() { EnigmaThrowable enigmaThrowable = assertThrowsExactly(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsThrowableWithMessage() { EnigmaThrowable enigmaThrowable = assertThrowsExactly(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }, "message"); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsThrowableWithMessageSupplier() { EnigmaThrowable enigmaThrowable = assertThrowsExactly(EnigmaThrowable.class, () -> { throw new EnigmaThrowable(); }, () -> "message"); assertNotNull(enigmaThrowable); } @Test void assertThrowsWithExecutableThatThrowsCheckedException() { IOException exception = assertThrowsExactly(IOException.class, () -> { throw new IOException(); }); assertNotNull(exception); } @Test void assertThrowsWithExecutableThatThrowsRuntimeException() { IllegalStateException illegalStateException = assertThrowsExactly(IllegalStateException.class, () -> { throw new IllegalStateException(); }); assertNotNull(illegalStateException); } @Test void assertThrowsWithExecutableThatThrowsError() { StackOverflowError stackOverflowError = assertThrowsExactly(StackOverflowError.class, AssertionTestUtils::recurseIndefinitely); assertNotNull(stackOverflowError); } @Test void assertThrowsWithExecutableThatDoesNotThrowAnException() { try { assertThrowsExactly(IllegalStateException.class, nix); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "Expected java.lang.IllegalStateException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatDoesNotThrowAnExceptionWithMessageString() { try { assertThrowsExactly(IOException.class, nix, "Custom message"); expectAssertionFailedError(); } catch (AssertionError ex) { assertMessageEquals(ex, "Custom message ==> Expected java.io.IOException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatDoesNotThrowAnExceptionWithMessageSupplier() { try { assertThrowsExactly(IOException.class, nix, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionError ex) { assertMessageEquals(ex, "Custom message ==> Expected java.io.IOException to be thrown, but nothing was thrown."); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedException() { try { assertThrowsExactly(IllegalStateException.class, () -> { throw new NumberFormatException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseExactlyInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageString() { try { assertThrowsExactly(IllegalStateException.class, () -> { throw new NumberFormatException(); }, "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like this: // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseExactlyInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageSupplier() { try { assertThrowsExactly(IllegalStateException.class, () -> { throw new NumberFormatException(); }, () -> "Custom message"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Should look something like this: // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); assertThat(ex).hasCauseExactlyInstanceOf(NumberFormatException.class); } } @Test @SuppressWarnings("serial") void assertThrowsWithExecutableThatThrowsInstanceOfAnonymousInnerClassAsUnexpectedException() { try { assertThrowsExactly(IllegalStateException.class, () -> { throw new NumberFormatException() { }; }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // As of the time of this writing, the class name of the above anonymous inner // class is org.junit.jupiter.api.AssertThrowsExactlyAssertionsTests$2; however, hard // coding "$2" is fragile. So we just check for the presence of the "$" // appended to this class's name. assertMessageContains(ex, "but was: <" + getClass().getName() + "$"); assertThat(ex).hasCauseInstanceOf(NumberFormatException.class); } } @Test void assertThrowsWithExecutableThatThrowsInstanceOfStaticNestedClassAsUnexpectedException() { try { assertThrowsExactly(IllegalStateException.class, () -> { throw new LocalException(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // The following verifies that the canonical name is used (i.e., "." instead of "$"). assertMessageContains(ex, "but was: <" + LocalException.class.getName().replace("$", ".") + ">"); assertThat(ex).hasCauseExactlyInstanceOf(LocalException.class); } } @Test @SuppressWarnings("unchecked") void assertThrowsWithExecutableThatThrowsSameExceptionTypeFromDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(EnigmaThrowable.class)) { // Load expected exception type from different class loader Class enigmaThrowableClass = (Class) testClassLoader.loadClass( EnigmaThrowable.class.getName()); try { assertThrowsExactly(enigmaThrowableClass, () -> { throw new EnigmaThrowable(); }); expectAssertionFailedError(); } catch (AssertionFailedError ex) { // Example Output: // // Unexpected exception type thrown, // expected: // but was: assertMessageStartsWith(ex, "Unexpected exception type thrown, "); // The presence of the "@" sign is sufficient to indicate that the hash was // generated to disambiguate between the two identical class names. assertMessageContains(ex, "expected: changed = ThreadLocal.withInitial(() -> new AtomicBoolean(false)); private final Executable nix = () -> { }; // --- executable ---------------------------------------------------------- @Test void assertTimeoutForExecutableThatCompletesBeforeTheTimeout() { changed.get().set(false); assertTimeout(ofMillis(500), () -> changed.get().set(true)); assertTrue(changed.get().get(), "should have executed in the same thread"); assertTimeout(ofMillis(500), nix, "message"); assertTimeout(ofMillis(500), nix, () -> "message"); } @Test void assertTimeoutForExecutableThatThrowsAnException() { RuntimeException exception = assertThrows(RuntimeException.class, () -> assertTimeout(ofMillis(500), () -> { throw new RuntimeException("not this time"); })); assertMessageEquals(exception, "not this time"); } @Test void assertTimeoutForExecutableThatThrowsAnAssertionFailedError() { AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> assertTimeout(ofMillis(500), () -> fail("enigma"))); assertMessageEquals(exception, "enigma"); } @Test void assertTimeoutForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeout(ofMillis(10), this::nap)); assertMessageStartsWith(error, "execution exceeded timeout of 10 ms by"); } @Test void assertTimeoutWithMessageForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeout(ofMillis(10), this::nap, "Tempus Fugit")); assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by"); } @Test void assertTimeoutWithMessageSupplierForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeout(ofMillis(10), this::nap, () -> "Tempus" + " " + "Fugit")); assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by"); } // --- supplier ------------------------------------------------------------ @Test void assertTimeoutForSupplierThatCompletesBeforeTheTimeout() { changed.get().set(false); String result = assertTimeout(ofMillis(500), () -> { changed.get().set(true); return "Tempus Fugit"; }); assertTrue(changed.get().get(), "should have executed in the same thread"); assertEquals("Tempus Fugit", result); assertEquals("Tempus Fugit", assertTimeout(ofMillis(500), () -> "Tempus Fugit", "message")); assertEquals("Tempus Fugit", assertTimeout(ofMillis(500), () -> "Tempus Fugit", () -> "message")); } @Test void assertTimeoutForSupplierThatThrowsAnException() { RuntimeException exception = assertThrows(RuntimeException.class, () -> { assertTimeout(ofMillis(500), () -> { ExceptionUtils.throwAsUncheckedException(new RuntimeException("not this time")); return "Tempus Fugit"; }); }); assertMessageEquals(exception, "not this time"); } @Test void assertTimeoutForSupplierThatThrowsAnAssertionFailedError() { AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> { assertTimeout(ofMillis(500), () -> { fail("enigma"); return "Tempus Fugit"; }); }); assertMessageEquals(exception, "enigma"); } @Test void assertTimeoutForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeout(ofMillis(10), () -> { nap(); return "Tempus Fugit"; }); }); assertMessageStartsWith(error, "execution exceeded timeout of 10 ms by"); } @Test void assertTimeoutWithMessageForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeout(ofMillis(10), () -> { nap(); return "Tempus Fugit"; }, "Tempus Fugit"); }); assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by"); } @Test void assertTimeoutWithMessageSupplierForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeout(ofMillis(10), () -> { nap(); return "Tempus Fugit"; }, () -> "Tempus" + " " + "Fugit"); }); assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by"); } /** * Take a nap for 100 milliseconds. */ private void nap() throws InterruptedException { long start = System.currentTimeMillis(); // workaround for imprecise clocks (yes, Windows, I'm talking about you) do { Thread.sleep(100); } while (System.currentTimeMillis() - start < 100); } } AssertTimeoutPreemptivelyAssertionsTests.java000066400000000000000000000242761455764576500372600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.time.Duration.ofMillis; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.OS.WINDOWS; import java.time.Duration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.ExceptionUtils; import org.opentest4j.AssertionFailedError; /** * Unit tests for {@link AssertTimeoutPreemptively}. * * @since 5.0 */ class AssertTimeoutPreemptivelyAssertionsTests { private static final Duration PREEMPTIVE_TIMEOUT = ofMillis(WINDOWS.isCurrentOs() ? 1000 : 100); private static final Assertions.TimeoutFailureFactory TIMEOUT_EXCEPTION_FACTORY = (__, ___, ____) -> new TimeoutException(); private static final ThreadLocal changed = ThreadLocal.withInitial(() -> new AtomicBoolean(false)); private final Executable nix = () -> { }; // --- executable ---------------------------------------------------------- @Test void assertTimeoutPreemptivelyForExecutableThatCompletesBeforeTheTimeout() { changed.get().set(false); assertTimeoutPreemptively(ofMillis(500), () -> changed.get().set(true)); assertFalse(changed.get().get(), "should have executed in a different thread"); assertTimeoutPreemptively(ofMillis(500), nix, "message"); assertTimeoutPreemptively(ofMillis(500), nix, () -> "message"); } @Test void assertTimeoutPreemptivelyForExecutableThatThrowsAnException() { RuntimeException exception = assertThrows(RuntimeException.class, () -> assertTimeoutPreemptively(ofMillis(500), () -> { throw new RuntimeException("not this time"); })); assertMessageEquals(exception, "not this time"); } @Test void assertTimeoutPreemptivelyForExecutableThatThrowsAnAssertionFailedError() { AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> assertTimeoutPreemptively(ofMillis(500), () -> fail("enigma"))); assertMessageEquals(exception, "enigma"); } @Test void assertTimeoutPreemptivelyForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, this::waitForInterrupt)); assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyWithMessageForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, this::waitForInterrupt, "Tempus Fugit")); assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, this::waitForInterrupt, () -> "Tempus" + " " + "Fugit")); assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesBeforeTheTimeout() { assertTimeoutPreemptively(ofMillis(500), nix, () -> "Tempus" + " " + "Fugit"); } // --- supplier ------------------------------------------------------------ @Test void assertTimeoutPreemptivelyForSupplierThatCompletesBeforeTheTimeout() { changed.get().set(false); String result = assertTimeoutPreemptively(ofMillis(500), () -> { changed.get().set(true); return "Tempus Fugit"; }); assertFalse(changed.get().get(), "should have executed in a different thread"); assertEquals("Tempus Fugit", result); assertEquals("Tempus Fugit", assertTimeoutPreemptively(ofMillis(500), () -> "Tempus Fugit", "message")); assertEquals("Tempus Fugit", assertTimeoutPreemptively(ofMillis(500), () -> "Tempus Fugit", () -> "message")); } @Test void assertTimeoutPreemptivelyForSupplierThatThrowsAnException() { RuntimeException exception = assertThrows(RuntimeException.class, () -> { assertTimeoutPreemptively(ofMillis(500), () -> { ExceptionUtils.throwAsUncheckedException(new RuntimeException("not this time")); return "Tempus Fugit"; }); }); assertMessageEquals(exception, "not this time"); } @Test void assertTimeoutPreemptivelyForSupplierThatThrowsAnAssertionFailedError() { AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> { assertTimeoutPreemptively(ofMillis(500), () -> { fail("enigma"); return "Tempus Fugit"; }); }); assertMessageEquals(exception, "enigma"); } @Test void assertTimeoutPreemptivelyForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, () -> { waitForInterrupt(); return "Tempus Fugit"; }); }); assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyWithMessageForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, () -> { waitForInterrupt(); return "Tempus Fugit"; }, "Tempus Fugit"); }); assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyWithMessageSupplierForSupplierThatCompletesAfterTheTimeout() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> { assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, () -> { waitForInterrupt(); return "Tempus Fugit"; }, () -> "Tempus" + " " + "Fugit"); }); assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyUsesThreadsWithSpecificNamePrefix() { AtomicReference threadName = new AtomicReference<>(""); assertTimeoutPreemptively(ofMillis(1000), () -> threadName.set(Thread.currentThread().getName())); assertTrue(threadName.get().startsWith("junit-timeout-thread-"), "Thread name does not match the expected prefix"); } @Test void assertTimeoutPreemptivelyThrowingTimeoutExceptionWithMessageForSupplierThatCompletesAfterTheTimeout() { assertThrows(TimeoutException.class, () -> Assertions.assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, () -> { waitForInterrupt(); return "Tempus Fugit"; }, () -> "Tempus Fugit", TIMEOUT_EXCEPTION_FACTORY)); } @Test void assertTimeoutPreemptivelyThrowingTimeoutExceptionWithMessageForSupplierThatThrowsAnAssertionFailedError() { AssertionFailedError exception = assertThrows(AssertionFailedError.class, () -> Assertions.assertTimeoutPreemptively(ofMillis(500), () -> fail("enigma"), () -> "Tempus Fugit", TIMEOUT_EXCEPTION_FACTORY)); assertMessageEquals(exception, "enigma"); } @Test void assertTimeoutPreemptivelyThrowingTimeoutExceptionWithMessageForSupplierThatThrowsAnException() { RuntimeException exception = assertThrows(RuntimeException.class, () -> Assertions.assertTimeoutPreemptively(ofMillis(500), () -> ExceptionUtils.throwAsUncheckedException(new RuntimeException(":(")), () -> "Tempus Fugit", TIMEOUT_EXCEPTION_FACTORY)); assertMessageEquals(exception, ":("); } @Test void assertTimeoutPreemptivelyThrowingTimeoutExceptionWithMessageForSupplierThatCompletesBeforeTimeout() throws Exception { var result = Assertions.assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, () -> "Tempus Fugit", () -> "Tempus Fugit", TIMEOUT_EXCEPTION_FACTORY); assertThat(result).isEqualTo("Tempus Fugit"); } private void waitForInterrupt() { try { assertFalse(Thread.interrupted(), "Already interrupted"); new CountDownLatch(1).await(); } catch (InterruptedException ignore) { // ignore } } /** * Assert the given stack trace elements contain an element with the given class name and method name. */ private static void assertStackTraceContains(StackTraceElement[] stackTrace, String className, String methodName) { assertThat(stackTrace).anySatisfy(element -> { assertThat(element.getClassName()).endsWith(className); assertThat(element.getMethodName()).isEqualTo(methodName); }); } } AssertTrueAssertionsTests.java000066400000000000000000000054641455764576500341410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertExpectedAndActualValues; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertTrue; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class AssertTrueAssertionsTests { @Test void assertTrueWithBooleanTrue() { assertTrue(true); assertTrue(true, "test"); assertTrue(true, () -> "test"); } @Test void assertTrueWithBooleanSupplierTrue() { assertTrue(() -> true); assertTrue(() -> true, "test"); assertTrue(() -> true, () -> "test"); } @Test void assertTrueWithBooleanTrueAndMessageSupplier() { assertTrue(true, () -> "test"); } @Test void assertTrueWithBooleanSupplierTrueAndMessageSupplier() { assertTrue(() -> true, () -> "test"); } @Test void assertTrueWithBooleanFalseAndDefaultMessageWithExpectedAndActualValues() { try { assertTrue(false); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "expected: but was: "); assertExpectedAndActualValues(ex, true, false); } } @Test void assertTrueWithBooleanFalseAndString() { try { assertTrue(false, "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, true, false); } } @Test void assertTrueWithBooleanFalseAndMessageSupplier() { try { assertTrue(false, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, true, false); } } @Test void assertTrueWithBooleanSupplierFalseAndString() { try { assertTrue(() -> false, "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, true, false); } } @Test void assertTrueWithBooleanSupplierFalseAndMessageSupplier() { try { assertTrue(() -> false, () -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test ==> expected: but was: "); assertExpectedAndActualValues(ex, true, false); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java000066400000000000000000000064741455764576500326530ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import java.io.Serializable; import java.util.Objects; import org.opentest4j.AssertionFailedError; import org.opentest4j.ValueWrapper; class AssertionTestUtils { private AssertionTestUtils() { /* no-op */ } static void expectAssertionFailedError() { throw new AssertionError("Should have thrown an " + AssertionFailedError.class.getName()); } static void assertEmptyMessage(Throwable ex) throws AssertionError { if (!ex.getMessage().isEmpty()) { throw new AssertionError("Exception message should be empty, but was [" + ex.getMessage() + "]."); } } static void assertMessageEquals(Throwable ex, String msg) throws AssertionError { if (!msg.equals(ex.getMessage())) { throw new AssertionError("Exception message should be [" + msg + "], but was [" + ex.getMessage() + "]."); } } static void assertMessageMatches(Throwable ex, String regex) throws AssertionError { if (!ex.getMessage().matches(regex)) { throw new AssertionError("Exception message should match regular expression [" + regex + "], but was [" + ex.getMessage() + "]."); } } static void assertMessageStartsWith(Throwable ex, String msg) throws AssertionError { if (!ex.getMessage().startsWith(msg)) { throw new AssertionError( "Exception message should start with [" + msg + "], but was [" + ex.getMessage() + "]."); } } static void assertMessageEndsWith(Throwable ex, String msg) throws AssertionError { if (!ex.getMessage().endsWith(msg)) { throw new AssertionError( "Exception message should end with [" + msg + "], but was [" + ex.getMessage() + "]."); } } static void assertMessageContains(Throwable ex, String msg) throws AssertionError { if (!ex.getMessage().contains(msg)) { throw new AssertionError( "Exception message should contain [" + msg + "], but was [" + ex.getMessage() + "]."); } } static void assertExpectedAndActualValues(AssertionFailedError ex, Object expected, Object actual) throws AssertionError { if (!wrapsEqualValue(ex.getExpected(), expected)) { throw new AssertionError("Expected value in AssertionFailedError should equal [" + ValueWrapper.create(expected) + "], but was [" + ex.getExpected() + "]."); } if (!wrapsEqualValue(ex.getActual(), actual)) { throw new AssertionError("Actual value in AssertionFailedError should equal [" + ValueWrapper.create(actual) + "], but was [" + ex.getActual() + "]."); } } static boolean wrapsEqualValue(ValueWrapper wrapper, Object value) { if (value == null || value instanceof Serializable) { return Objects.equals(value, wrapper.getValue()); } return wrapper.getIdentityHashCode() == System.identityHashCode(value) && Objects.equals(wrapper.getStringRepresentation(), String.valueOf(value)) && Objects.equals(wrapper.getType(), value.getClass()); } static void recurseIndefinitely() { // simulate infinite recursion throw new StackOverflowError(); } static void runOutOfMemory() { // simulate running out of memory throw new OutOfMemoryError("boom"); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssumptionsTests.java000066400000000000000000000144721455764576500323700ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.abort; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.Assumptions.assumingThat; import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.junit.jupiter.api.function.Executable; import org.opentest4j.TestAbortedException; /** * Unit tests for JUnit Jupiter {@link Assumptions}. * * @since 5.0 */ class AssumptionsTests { // --- assumeTrue ---------------------------------------------------- @Test void assumeTrueWithBooleanTrue() { String foo = null; try { assumeTrue(true); assumeTrue(true, "message"); assumeTrue(true, () -> "message"); foo = "foo"; } finally { assertNotNull(foo); } } @Test void assumeTrueWithBooleanSupplierTrue() { String foo = null; try { assumeTrue(() -> true); assumeTrue(() -> true, "message"); assumeTrue(() -> true, () -> "message"); foo = "foo"; } finally { assertNotNull(foo); } } @Test void assumeTrueWithBooleanFalse() { assertAssumptionFailure("assumption is not true", () -> assumeTrue(false)); } @Test void assumeTrueWithBooleanSupplierFalse() { assertAssumptionFailure("assumption is not true", () -> assumeTrue(() -> false)); } @Test void assumeTrueWithBooleanFalseAndStringMessage() { assertAssumptionFailure("test", () -> assumeTrue(false, "test")); } @Test void assumeTrueWithBooleanFalseAndNullStringMessage() { assertAssumptionFailure(null, () -> assumeTrue(false, (String) null)); } @Test void assumeTrueWithBooleanSupplierFalseAndStringMessage() { assertAssumptionFailure("test", () -> assumeTrue(() -> false, "test")); } @Test void assumeTrueWithBooleanSupplierFalseAndMessageSupplier() { assertAssumptionFailure("test", () -> assumeTrue(() -> false, () -> "test")); } @Test void assumeTrueWithBooleanFalseAndMessageSupplier() { assertAssumptionFailure("test", () -> assumeTrue(false, () -> "test")); } // --- assumeFalse ---------------------------------------------------- @Test void assumeFalseWithBooleanFalse() { String foo = null; try { assumeFalse(false); assumeFalse(false, "message"); assumeFalse(false, () -> "message"); foo = "foo"; } finally { assertNotNull(foo); } } @Test void assumeFalseWithBooleanSupplierFalse() { String foo = null; try { assumeFalse(() -> false); assumeFalse(() -> false, "message"); assumeFalse(() -> false, () -> "message"); foo = "foo"; } finally { assertNotNull(foo); } } @Test void assumeFalseWithBooleanTrue() { assertAssumptionFailure("assumption is not false", () -> assumeFalse(true)); } @Test void assumeFalseWithBooleanSupplierTrue() { assertAssumptionFailure("assumption is not false", () -> assumeFalse(() -> true)); } @Test void assumeFalseWithBooleanTrueAndStringMessage() { assertAssumptionFailure("test", () -> assumeFalse(true, "test")); } @Test void assumeFalseWithBooleanSupplierTrueAndMessage() { assertAssumptionFailure("test", () -> assumeFalse(() -> true, "test")); } @Test void assumeFalseWithBooleanSupplierTrueAndMessageSupplier() { assertAssumptionFailure("test", () -> assumeFalse(() -> true, () -> "test")); } @Test void assumeFalseWithBooleanTrueAndMessageSupplier() { assertAssumptionFailure("test", () -> assumeFalse(true, () -> "test")); } // --- assumingThat -------------------------------------------------- @Test void assumingThatWithBooleanTrue() { List list = new ArrayList<>(); assumingThat(true, () -> list.add("test")); assertEquals(1, list.size()); assertEquals("test", list.get(0)); } @Test void assumingThatWithBooleanSupplierTrue() { List list = new ArrayList<>(); assumingThat(() -> true, () -> list.add("test")); assertEquals(1, list.size()); assertEquals("test", list.get(0)); } @Test void assumingThatWithBooleanFalse() { List list = new ArrayList<>(); assumingThat(false, () -> list.add("test")); assertEquals(0, list.size()); } @Test void assumingThatWithBooleanSupplierFalse() { List list = new ArrayList<>(); assumingThat(() -> false, () -> list.add("test")); assertEquals(0, list.size()); } @Test void assumingThatWithFailingExecutable() { assertThrows(EnigmaThrowable.class, () -> assumingThat(true, () -> { throw new EnigmaThrowable(); })); } // --- abort --------------------------------------------------------- @Test void abortWithNoArguments() { assertTestAbortedException(null, Assumptions::abort); } @Test void abortWithStringMessage() { assertTestAbortedException("test", () -> abort("test")); } @Test void abortWithStringSupplier() { assertTestAbortedException("test", () -> abort(() -> "test")); } // ------------------------------------------------------------------- private static void assertAssumptionFailure(String msg, Executable executable) { assertTestAbortedException(msg == null ? "Assumption failed" : "Assumption failed: " + msg, executable); } private static void assertTestAbortedException(String expectedMessage, Executable executable) { try { executable.execute(); expectTestAbortedException(); } catch (Throwable ex) { assertTrue(ex instanceof TestAbortedException); assertMessageEquals(ex, expectedMessage); } } private static void expectTestAbortedException() { throw new AssertionError("Should have thrown a " + TestAbortedException.class.getName()); } private static void assertMessageEquals(Throwable t, String expectedMessage) throws AssertionError { if (!Objects.equals(expectedMessage, t.getMessage())) { throw new AssertionError("Message in TestAbortedException should be [" + expectedMessage + "], but was [" + t.getMessage() + "]."); } } } DisplayNameGenerationInheritanceTestCase.java000066400000000000000000000012761455764576500367670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; /** * @since 5.8 */ @DisplayNameGeneration(ReplaceUnderscores.class) class DisplayNameGenerationInheritanceTestCase { @Nested class InnerNestedTestCase { @Test void this_is_a_test() { } } static class StaticNestedTestCase { @Test void this_is_a_test() { } } } DisplayNameGenerationTests.java000066400000000000000000000312431455764576500342010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.lang.reflect.Method; import java.util.EmptyStackException; import java.util.Stack; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.engine.TestDescriptor; /** * Check generated display names. * * @see DisplayName * @see DisplayNameGenerator * @see DisplayNameGeneration * @since 5.4 */ class DisplayNameGenerationTests extends AbstractJupiterTestEngineTests { @Test void standardGenerator() { check(DefaultStyleTestCase.class, // "CONTAINER: DisplayNameGenerationTests$DefaultStyleTestCase", // "TEST: @DisplayName prevails", // "TEST: test()", // "TEST: test(TestInfo)", // "TEST: testUsingCamelCaseStyle()", // "TEST: testUsingCamelCase_and_also_UnderScores()", // "TEST: testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact(TestInfo)", // "TEST: test_with_underscores()" // ); } @Test void simpleGenerator() { check(SimpleStyleTestCase.class, // "CONTAINER: DisplayNameGenerationTests$SimpleStyleTestCase", // "TEST: @DisplayName prevails", // "TEST: test", // "TEST: test (TestInfo)", // "TEST: testUsingCamelCaseStyle", // "TEST: testUsingCamelCase_and_also_UnderScores", // "TEST: testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact (TestInfo)", // "TEST: test_with_underscores" // ); } @Test void underscoreGenerator() { var expectedDisplayNames = new String[] { // "", // "TEST: @DisplayName prevails", // "TEST: test", // "TEST: test (TestInfo)", // "TEST: test with underscores", // "TEST: testUsingCamelCase and also UnderScores", // "TEST: testUsingCamelCase and also UnderScores keepingParameterTypeNamesIntact (TestInfo)", // "TEST: testUsingCamelCaseStyle" // }; expectedDisplayNames[0] = "CONTAINER: DisplayNameGenerationTests$UnderscoreStyleTestCase"; check(UnderscoreStyleTestCase.class, expectedDisplayNames); expectedDisplayNames[0] = "CONTAINER: DisplayNameGenerationTests$UnderscoreStyleInheritedFromSuperClassTestCase"; check(UnderscoreStyleInheritedFromSuperClassTestCase.class, expectedDisplayNames); } @Test void indicativeSentencesGeneratorOnStaticNestedClass() { check(IndicativeStyleTestCase.class, // "CONTAINER: DisplayNameGenerationTests$IndicativeStyleTestCase", // "TEST: @DisplayName prevails", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test (TestInfo)", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> test with underscores", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCase and also UnderScores", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCase and also UnderScores keepingParameterTypeNamesIntact (TestInfo)", // "TEST: DisplayNameGenerationTests$IndicativeStyleTestCase -> testUsingCamelCaseStyle" // ); } @Test void indicativeSentencesGeneratorOnTopLevelClass() { check(IndicativeSentencesTopLevelTestCase.class, // "CONTAINER: IndicativeSentencesTopLevelTestCase", // "CONTAINER: IndicativeSentencesTopLevelTestCase -> A year is a leap year", // "TEST: IndicativeSentencesTopLevelTestCase -> A year is a leap year -> if it is divisible by 4 but not by 100" // ); } @Test void indicativeSentencesGeneratorOnNestedClass() { check(IndicativeSentencesNestedTestCase.class, // "CONTAINER: IndicativeSentencesNestedTestCase", // "CONTAINER: A year is a leap year", // "TEST: A year is a leap year -> if it is divisible by 4 but not by 100" // ); } @Test void noNameGenerator() { check(NoNameStyleTestCase.class, // "CONTAINER: nn", // "TEST: @DisplayName prevails", // "TEST: nn", // "TEST: nn", // "TEST: nn", // "TEST: nn", // "TEST: nn", // "TEST: nn" // ); } @Test void checkDisplayNameGeneratedForTestingAStackDemo() { check(StackTestCase.class, // "CONTAINER: A stack", // "TEST: is instantiated using its noarg constructor", // "CONTAINER: A new stack", // "TEST: throws an EmptyStackException when peeked", // "TEST: throws an EmptyStackException when popped", // "TEST: is empty", // "CONTAINER: After pushing an element to an empty stack", // "TEST: peek returns that element without removing it from the stack", // "TEST: pop returns that element and leaves an empty stack", // "TEST: the stack is no longer empty" // ); } @Test void checkDisplayNameGeneratedForIndicativeGeneratorTestCase() { check(IndicativeGeneratorTestCase.class, // "CONTAINER: A stack", // "TEST: A stack, is instantiated with new constructor", // "CONTAINER: A stack, when new", // "TEST: A stack, when new, throws EmptyStackException when peeked", // "CONTAINER: A stack, when new, after pushing an element to an empty stack", // "TEST: A stack, when new, after pushing an element to an empty stack, is no longer empty" // ); } @Test void checkDisplayNameGeneratedForIndicativeGeneratorWithCustomSeparatorTestCase() { check(IndicativeGeneratorWithCustomSeparatorTestCase.class, // "CONTAINER: A stack", // "TEST: A stack >> is instantiated with new constructor", // "CONTAINER: A stack >> when new", // "TEST: A stack >> when new >> throws EmptyStackException when peeked", // "CONTAINER: A stack >> when new >> after pushing an element to an empty stack", // "TEST: A stack >> when new >> after pushing an element to an empty stack >> is no longer empty" // ); } @Test void displayNameGenerationInheritance() { check(DisplayNameGenerationInheritanceTestCase.InnerNestedTestCase.class, // "CONTAINER: DisplayNameGenerationInheritanceTestCase", // "CONTAINER: InnerNestedTestCase", // "TEST: this is a test"// ); check(DisplayNameGenerationInheritanceTestCase.StaticNestedTestCase.class, // "CONTAINER: DisplayNameGenerationInheritanceTestCase$StaticNestedTestCase", // "TEST: this_is_a_test()"// ); } @Test void indicativeSentencesGenerationInheritance() { check(IndicativeSentencesGenerationInheritanceTestCase.InnerNestedTestCase.class, // "CONTAINER: IndicativeSentencesGenerationInheritanceTestCase", // "CONTAINER: IndicativeSentencesGenerationInheritanceTestCase -> InnerNestedTestCase", // "TEST: IndicativeSentencesGenerationInheritanceTestCase -> InnerNestedTestCase -> this is a test"// ); check(IndicativeSentencesGenerationInheritanceTestCase.StaticNestedTestCase.class, // "CONTAINER: IndicativeSentencesGenerationInheritanceTestCase$StaticNestedTestCase", // "TEST: this_is_a_test()"// ); } private void check(Class testClass, String... expectedDisplayNames) { var request = request().selectors(selectClass(testClass)).build(); var descriptors = discoverTests(request).getDescendants(); assertThat(descriptors).map(this::describe).containsExactlyInAnyOrder(expectedDisplayNames); } private String describe(TestDescriptor descriptor) { return descriptor.getType() + ": " + descriptor.getDisplayName(); } // ------------------------------------------------------------------- static class NoNameGenerator implements DisplayNameGenerator { @Override public String generateDisplayNameForClass(Class testClass) { return "nn"; } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return "nn"; } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return "nn"; } } @DisplayNameGeneration(NoNameGenerator.class) static abstract class AbstractTestCase { @Test void test() { } @Test void test(TestInfo testInfo) { testInfo.getDisplayName(); } @Test void testUsingCamelCaseStyle() { } @Test void testUsingCamelCase_and_also_UnderScores() { } @Test void testUsingCamelCase_and_also_UnderScores_keepingParameterTypeNamesIntact(TestInfo testInfo) { testInfo.getDisplayName(); } @Test void test_with_underscores() { } @DisplayName("@DisplayName prevails") @Test void testDisplayNamePrevails() { } } @DisplayNameGeneration(DisplayNameGenerator.Standard.class) static class DefaultStyleTestCase extends AbstractTestCase { } @DisplayNameGeneration(DisplayNameGenerator.Simple.class) static class SimpleStyleTestCase extends AbstractTestCase { } @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) static class UnderscoreStyleTestCase extends AbstractTestCase { } @IndicativeSentencesGeneration(separator = " -> ", generator = DisplayNameGenerator.ReplaceUnderscores.class) static class IndicativeStyleTestCase extends AbstractTestCase { } @DisplayNameGeneration(NoNameGenerator.class) static class NoNameStyleTestCase extends AbstractTestCase { } // No annotation here! @DisplayNameGeneration is inherited from super class static class UnderscoreStyleInheritedFromSuperClassTestCase extends UnderscoreStyleTestCase { } // ------------------------------------------------------------------- @DisplayName("A stack") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) static class StackTestCase { Stack stack; @Test void is_instantiated_using_its_noarg_constructor() { new Stack<>(); } @Nested class A_new_stack { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test void is_empty() { assertTrue(stack.isEmpty()); } @Test void throws_an_EmptyStackException_when_popped() { assertThrows(EmptyStackException.class, () -> stack.pop()); } @Test void throws_an_EmptyStackException_when_peeked() { assertThrows(EmptyStackException.class, () -> stack.peek()); } @Nested class After_pushing_an_element_to_an_empty_stack { String anElement = "an element"; @BeforeEach void pushAnElement() { stack.push(anElement); } @Test void the_stack_is_no_longer_empty() { assertFalse(stack.isEmpty()); } @Test void pop_returns_that_element_and_leaves_an_empty_stack() { assertEquals(anElement, stack.pop()); assertTrue(stack.isEmpty()); } @Test void peek_returns_that_element_without_removing_it_from_the_stack() { assertEquals(anElement, stack.peek()); assertFalse(stack.isEmpty()); } } } } // ------------------------------------------------------------------- @DisplayName("A stack") @IndicativeSentencesGeneration(generator = DisplayNameGenerator.ReplaceUnderscores.class) static class IndicativeGeneratorTestCase { Stack stack; @Test void is_instantiated_with_new_constructor() { new Stack<>(); } @Nested class when_new { @BeforeEach void create_with_new_stack() { stack = new Stack<>(); } @Test void throws_EmptyStackException_when_peeked() { assertThrows(EmptyStackException.class, () -> stack.peek()); } @Nested class after_pushing_an_element_to_an_empty_stack { String anElement = "an element"; @BeforeEach void push_an_element() { stack.push(anElement); } @Test void is_no_longer_empty() { assertFalse(stack.isEmpty()); } } } } // ------------------------------------------------------------------- @DisplayName("A stack") @IndicativeSentencesGeneration(separator = " >> ", generator = DisplayNameGenerator.ReplaceUnderscores.class) static class IndicativeGeneratorWithCustomSeparatorTestCase { Stack stack; @Test void is_instantiated_with_new_constructor() { new Stack<>(); } @Nested class when_new { @BeforeEach void create_with_new_stack() { stack = new Stack<>(); } @Test void throws_EmptyStackException_when_peeked() { assertThrows(EmptyStackException.class, () -> stack.peek()); } @Nested class after_pushing_an_element_to_an_empty_stack { String anElement = "an element"; @BeforeEach void push_an_element() { stack.push(anElement); } @Test void is_no_longer_empty() { assertFalse(stack.isEmpty()); } } } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/DynamicTestTests.java000066400000000000000000000166221455764576500322660ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static java.util.Collections.emptyIterator; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; import org.opentest4j.AssertionFailedError; /** * @since 5.0 */ class DynamicTestTests { private static final Executable nix = () -> { }; private final List assertedValues = new ArrayList<>(); @Test void streamFromStreamPreconditions() { ThrowingConsumer testExecutor = input -> { }; Function displayNameGenerator = Object::toString; assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream((Stream) null, displayNameGenerator, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(Stream.empty(), null, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(Stream.empty(), displayNameGenerator, null)); } @Test void streamFromIteratorPreconditions() { ThrowingConsumer testExecutor = input -> { }; Function displayNameGenerator = Object::toString; assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream((Iterator) null, displayNameGenerator, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(emptyIterator(), null, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(emptyIterator(), displayNameGenerator, null)); } @Test void streamFromStreamWithNamesPreconditions() { ThrowingConsumer testExecutor = input -> { }; assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream((Stream>) null, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(Stream.empty(), null)); } @Test void streamFromIteratorWithNamesPreconditions() { ThrowingConsumer testExecutor = input -> { }; assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream((Iterator>) null, testExecutor)); assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(emptyIterator(), null)); } @Test void streamFromStream() throws Throwable { Stream stream = DynamicTest.stream(Stream.of("foo", "bar", "baz"), String::toUpperCase, this::throwingConsumer); assertStream(stream); } @Test void streamFromIterator() throws Throwable { Stream stream = DynamicTest.stream(List.of("foo", "bar", "baz").iterator(), String::toUpperCase, this::throwingConsumer); assertStream(stream); } @Test void streamFromStreamWithNames() throws Throwable { Stream stream = DynamicTest.stream( Stream.of(Named.of("FOO", "foo"), Named.of("BAR", "bar"), Named.of("BAZ", "baz")), this::throwingConsumer); assertStream(stream); } @Test void streamFromIteratorWithNames() throws Throwable { Stream stream = DynamicTest.stream( List.of(Named.of("FOO", "foo"), Named.of("BAR", "bar"), Named.of("BAZ", "baz")).iterator(), this::throwingConsumer); assertStream(stream); } private void assertStream(Stream stream) throws Throwable { List dynamicTests = stream.collect(Collectors.toList()); assertThat(dynamicTests).extracting(DynamicTest::getDisplayName).containsExactly("FOO", "BAR", "BAZ"); assertThat(assertedValues).isEmpty(); dynamicTests.get(0).getExecutable().execute(); assertThat(assertedValues).containsExactly("foo"); dynamicTests.get(1).getExecutable().execute(); assertThat(assertedValues).containsExactly("foo", "bar"); Throwable t = assertThrows(Throwable.class, () -> dynamicTests.get(2).getExecutable().execute()); assertThat(t).hasMessage("Baz!"); assertThat(assertedValues).containsExactly("foo", "bar"); } private void throwingConsumer(String str) throws Throwable { if ("baz".equals(str)) { throw new Throwable("Baz!"); } this.assertedValues.add(str); } @Test void reflectiveOperationsThrowingAssertionFailedError() { Throwable t48 = assertThrows(AssertionFailedError.class, () -> dynamicTest("1 == 48", this::assert1Equals48Directly).getExecutable().execute()); assertThat(t48).hasMessage("expected: <1> but was: <48>"); Throwable t49 = assertThrows(AssertionFailedError.class, () -> dynamicTest("1 == 49", this::assert1Equals49ReflectivelyAndUnwrapInvocationTargetException).getExecutable().execute()); assertThat(t49).hasMessage("expected: <1> but was: <49>"); } @Test void reflectiveOperationThrowingInvocationTargetException() { Throwable t50 = assertThrows(InvocationTargetException.class, () -> dynamicTest("1 == 50", this::assert1Equals50Reflectively).getExecutable().execute()); assertThat(t50.getCause()).hasMessage("expected: <1> but was: <50>"); } @Test void sourceUriIsNotPresentByDefault() { DynamicTest test = dynamicTest("foo", nix); assertThat(test.getTestSourceUri()).isNotPresent(); assertThat(test.toString()).isEqualTo("DynamicTest [displayName = 'foo', testSourceUri = null]"); DynamicContainer container = dynamicContainer("bar", Stream.of(test)); assertThat(container.getTestSourceUri()).isNotPresent(); assertThat(container.toString()).isEqualTo("DynamicContainer [displayName = 'bar', testSourceUri = null]"); } @Test void sourceUriIsReturnedWhenSupplied() { URI testSourceUri = URI.create("any://test"); DynamicTest test = dynamicTest("foo", testSourceUri, nix); URI containerSourceUri = URI.create("other://container"); DynamicContainer container = dynamicContainer("bar", containerSourceUri, Stream.of(test)); assertThat(test.getTestSourceUri()).containsSame(testSourceUri); assertThat(test.toString()).isEqualTo("DynamicTest [displayName = 'foo', testSourceUri = any://test]"); assertThat(container.getTestSourceUri()).containsSame(containerSourceUri); assertThat(container.toString()).isEqualTo( "DynamicContainer [displayName = 'bar', testSourceUri = other://container]"); } private void assert1Equals48Directly() { Assertions.assertEquals(1, 48); } private void assert1Equals49ReflectivelyAndUnwrapInvocationTargetException() throws Throwable { Method method = Assertions.class.getMethod("assertEquals", int.class, int.class); ReflectionSupport.invokeMethod(method, null, 1, 49); } private void assert1Equals50Reflectively() throws Throwable { Method method = Assertions.class.getMethod("assertEquals", int.class, int.class); method.invoke(null, 1, 50); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/EnigmaThrowable.java000066400000000000000000000011121455764576500320530ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; /** * This is a top-level type in order to avoid issues with * {@link Class#getCanonicalName()} when using different class * loaders in tests. * * @since 5.0 */ @SuppressWarnings("serial") class EnigmaThrowable extends Throwable { } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java000066400000000000000000000066441455764576500327730ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import static org.junit.jupiter.api.AssertionTestUtils.assertEmptyMessage; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageContains; import static org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals; import static org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.util.function.Supplier; import java.util.stream.Stream; import org.opentest4j.AssertionFailedError; /** * Unit tests for JUnit Jupiter {@link Assertions}. * * @since 5.0 */ class FailAssertionsTests { @Test void failWithoutArgument() { try { fail(); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertEmptyMessage(ex); } } @Test void failWithString() { try { fail("test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test"); } } @Test void failWithMessageSupplier() { try { fail(() -> "test"); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "test"); } } @Test void failWithNullString() { try { fail((String) null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertEmptyMessage(ex); } } @Test void failWithNullMessageSupplier() { try { fail((Supplier) null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertEmptyMessage(ex); } } @Test void failWithStringAndThrowable() { try { fail("message", new Throwable("cause")); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "message"); Throwable cause = ex.getCause(); assertMessageContains(cause, "cause"); } } @Test void failWithThrowable() { try { fail(new Throwable("cause")); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertEmptyMessage(ex); Throwable cause = ex.getCause(); assertMessageContains(cause, "cause"); } } @Test void failWithStringAndNullThrowable() { try { fail("message", (Throwable) null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertMessageEquals(ex, "message"); if (ex.getCause() != null) { throw new AssertionError("Cause should have been null"); } } } @Test void failWithNullStringAndThrowable() { try { fail((String) null, new Throwable("cause")); expectAssertionFailedError(); } catch (AssertionFailedError ex) { assertEmptyMessage(ex); Throwable cause = ex.getCause(); assertMessageContains(cause, "cause"); } } @Test void failUsableAsAnExpression() { // @formatter:off long count = Stream.empty() .peek(element -> fail("peek should never be called")) .filter(element -> fail("filter should never be called", new Throwable("cause"))) .map(element -> fail(new Throwable("map should never be called"))) .sorted((e1, e2) -> fail(() -> "sorted should never be called")) .count(); // @formatter:on assertEquals(0L, count); } } IndicativeSentencesGenerationInheritanceTestCase.java000066400000000000000000000013561455764576500405070ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; /** * @since 5.8 */ @IndicativeSentencesGeneration(separator = " -> ", generator = ReplaceUnderscores.class) class IndicativeSentencesGenerationInheritanceTestCase { @Nested class InnerNestedTestCase { @Test void this_is_a_test() { } } static class StaticNestedTestCase { @Test void this_is_a_test() { } } } IndicativeSentencesNestedTestCase.java000066400000000000000000000015441455764576500354630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; /** * This test case declares {@link IndicativeSentencesGeneration} on a test class * that is nested directly within a top-level test class. * * @see IndicativeSentencesTopLevelTestCase * @since 5.8 */ class IndicativeSentencesNestedTestCase { @Nested @IndicativeSentencesGeneration(separator = " -> ", generator = ReplaceUnderscores.class) class A_year_is_a_leap_year { @Test void if_it_is_divisible_by_4_but_not_by_100() { } } } IndicativeSentencesTopLevelTestCase.java000066400000000000000000000015311455764576500357670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; /** * This test case declares {@link IndicativeSentencesGeneration} on a top-level * test class that contains a nested test class. * * @see IndicativeSentencesNestedTestCase * @since 5.8 */ @IndicativeSentencesGeneration(separator = " -> ", generator = ReplaceUnderscores.class) class IndicativeSentencesTopLevelTestCase { @Nested class A_year_is_a_leap_year { @Test void if_it_is_divisible_by_4_but_not_by_100() { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/IterableFactory.java000066400000000000000000000012331455764576500320660ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; final class IterableFactory { static List listOf(Object... objects) { return Arrays.asList(objects); } static Set setOf(Object... objects) { return new LinkedHashSet<>(listOf(objects)); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/000077500000000000000000000000001455764576500301335ustar00rootroot00000000000000AbstractExecutionConditionTests.java000066400000000000000000000075351455764576500372520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.commons.util.ReflectionUtils.newInstance; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; /** * Abstract base class for unit testing a concrete {@link ExecutionCondition} * implementation. * *

WARNING: this abstract base class currently does not * support tests in {@code @Nested} test classes within the * {@linkplain #getTestClass() test class}, since {@link #beforeEach(TestInfo)} * instantiates the test class using the no-args default constructor. * * @since 5.1 */ @TestInstance(Lifecycle.PER_CLASS) abstract class AbstractExecutionConditionTests { private final ExtensionContext context = mock(); private ConditionEvaluationResult result; @BeforeAll void ensureAllTestMethodsAreCovered() { Predicate isTestMethod = method -> method.isAnnotationPresent(Test.class); List methodsToTest = findMethods(getTestClass(), isTestMethod).stream()// .map(Method::getName).sorted().collect(toList()); List localTestMethods = findMethods(getClass(), isTestMethod).stream()// .map(Method::getName).sorted().collect(toList()); assertThat(localTestMethods).isEqualTo(methodsToTest); } @BeforeEach void beforeEach(TestInfo testInfo) { when(this.context.getElement()).thenReturn(method(testInfo)); when(this.context.getTestInstance()).thenReturn(Optional.of(newInstance(getTestClass()))); doReturn(getTestClass()).when(this.context).getRequiredTestClass(); } protected abstract ExecutionCondition getExecutionCondition(); protected abstract Class getTestClass(); protected void evaluateCondition() { this.result = getExecutionCondition().evaluateExecutionCondition(this.context); } protected void assertEnabled() { assertTrue(!this.result.isDisabled(), "Should be enabled"); } protected void assertDisabled() { assertTrue(this.result.isDisabled(), "Should be disabled"); } protected void assertReasonContains(String text) { assertThat(this.result.getReason()).hasValueSatisfying(reason -> assertThat(reason).contains(text)); } protected void assertCustomDisabledReasonIs(String text) { if (this.result.isDisabled()) { assertThat(this.result.getReason()).hasValueSatisfying( reason -> assertThat(reason).contains(" ==> " + text)); } } private Optional method(TestInfo testInfo) { return method(getTestClass(), testInfo.getTestMethod().get().getName()); } private Optional method(Class testClass, String methodName) { return Optional.of(findMethod(testClass, methodName).get()); } } DisabledForJreRangeConditionTests.java000066400000000000000000000106301455764576500374050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DisabledForJreRange}. * *

Note that test method names MUST match the test method names in * {@link DisabledForJreRangeIntegrationTests}. * * @since 5.6 */ class DisabledForJreRangeConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new DisabledForJreRangeCondition(); } @Override protected Class getTestClass() { return DisabledForJreRangeIntegrationTests.class; } /** * @see DisabledForJreRangeIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@DisabledForJreRange is not present"); } /** * @see DisabledForJreRangeIntegrationTests#defaultValues() */ @Test void defaultValues() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// .withMessageContaining("You must declare a non-default value for min or max in @DisabledForJreRange"); } /** * @see DisabledForJreRangeIntegrationTests#java17() */ @Test void java17() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava17()); } /** * @see DisabledForJreRangeIntegrationTests#java18to19() */ @Test void java18to19() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava18() || onJava19()); assertCustomDisabledReasonIs("Disabled on some JRE"); } /** * @see DisabledForJreRangeIntegrationTests#javaMax18() */ @Test void javaMax18() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); } /** * @see DisabledForJreRangeIntegrationTests#javaMin18() */ @Test void javaMin18() { evaluateCondition(); assertDisabledOnCurrentJreIf(!(onJava17())); } /** * @see DisabledForJreRangeIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertDisabledOnCurrentJreIf( !(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22())); } private void assertDisabledOnCurrentJreIf(boolean condition) { if (condition) { assertDisabled(); assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); } else { assertEnabled(); assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); } } } DisabledForJreRangeIntegrationTests.java000066400000000000000000000065221455764576500377470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledForJreRange}. * * @since 5.6 */ class DisabledForJreRangeIntegrationTests { @Test void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @DisabledForJreRange void defaultValues() { fail("should result in a configuration exception"); } @Test @DisabledForJreRange(min = JAVA_17, max = JAVA_17) void java17() { assertFalse(onJava17()); } @Test @DisabledForJreRange(min = JAVA_18, max = JAVA_19, disabledReason = "Disabled on some JRE") void java18to19() { assertFalse(onJava18() || onJava19()); } @Test @DisabledForJreRange(max = JAVA_18) void javaMax18() { assertFalse(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); } @Test @DisabledForJreRange(min = JAVA_18) void javaMin18() { assertFalse(onJava18() || onJava19()); assertTrue(onJava17()); } @Test @DisabledForJreRange(min = OTHER, max = OTHER) void other() { assertTrue( onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22()); } } DisabledIfConditionClassLoaderTests.java000066400000000000000000000051401455764576500377140ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; /** * Tests for {@link DisabledIfCondition} using custom {@link ClassLoader} arrangements. * * @since 5.10 */ public class DisabledIfConditionClassLoaderTests { @Test // No need to introduce a "disabled" version of this test, since it would simply be the // logical inverse of this method and would therefore not provide any further benefit. void enabledWithStaticMethodInTypeFromDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(getClass(), StaticConditionMethods.class)) { var testClass = testClassLoader.loadClass(getClass().getName()); assertThat(testClass.getClassLoader()).isSameAs(testClassLoader); ExtensionContext context = mock(); Method annotatedMethod = ReflectionUtils.findMethod(getClass(), "enabledMethod").get(); when(context.getElement()).thenReturn(Optional.of(annotatedMethod)); doReturn(testClass).when(context).getRequiredTestClass(); DisabledIfCondition condition = new DisabledIfCondition(); ConditionEvaluationResult result = condition.evaluateExecutionCondition(context); assertThat(result).isNotNull(); assertThat(result.isDisabled()).isFalse(); Method conditionMethod = condition.getConditionMethod( "org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse", context); assertThat(conditionMethod).isNotNull(); Class declaringClass = conditionMethod.getDeclaringClass(); assertThat(declaringClass.getClassLoader()).isSameAs(testClassLoader); assertThat(declaringClass.getName()).isEqualTo(StaticConditionMethods.class.getName()); assertThat(declaringClass).isNotEqualTo(StaticConditionMethods.class); } } @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") private void enabledMethod() { } } DisabledIfConditionTests.java000066400000000000000000000057721455764576500356120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; /** * Unit tests for {@link DisabledIf}. * *

Note that test method names MUST match the test method names in * {@link DisabledIfIntegrationTests}. * * @since 5.7 */ public class DisabledIfConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new DisabledIfCondition(); } @Override protected Class getTestClass() { return DisabledIfIntegrationTests.class; } /** * @see DisabledIfIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@DisabledIf is not present"); } /** * @see DisabledIfIntegrationTests#disabledBecauseStaticConditionMethodReturnsTrue() */ @Test void disabledBecauseStaticConditionMethodReturnsTrue() { evaluateCondition(); assertDisabled(); assertReasonContains("Disabled for some reason"); } /** * @see DisabledIfIntegrationTests#enabledBecauseStaticConditionMethodReturnsFalse() */ @Test void enabledBecauseStaticConditionMethodReturnsFalse() { evaluateCondition(); assertEnabled(); assertReasonContains(""" @DisabledIf("staticMethodThatReturnsFalse") evaluated to false"""); } /** * @see DisabledIfIntegrationTests#disabledBecauseConditionMethodReturnsTrue() */ @Test void disabledBecauseConditionMethodReturnsTrue() { evaluateCondition(); assertDisabled(); assertReasonContains(""" @DisabledIf("methodThatReturnsTrue") evaluated to true"""); } /** * @see DisabledIfIntegrationTests#enabledBecauseConditionMethodReturnsFalse() */ @Test void enabledBecauseConditionMethodReturnsFalse() { evaluateCondition(); assertEnabled(); assertReasonContains(""" @DisabledIf("methodThatReturnsFalse") evaluated to false"""); } /** * @see DisabledIfIntegrationTests.ExternalConditionMethod#disabledBecauseStaticExternalConditionMethodReturnsTrue() */ @Test void disabledBecauseStaticExternalConditionMethodReturnsTrue() { evaluateCondition(); assertDisabled(); assertReasonContains(""" @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") evaluated to true"""); } /** * @see DisabledIfIntegrationTests.ExternalConditionMethod#enabledBecauseStaticExternalConditionMethodReturnsFalse() */ @Test void enabledBecauseStaticExternalConditionMethodReturnsFalse() { evaluateCondition(); assertEnabled(); assertReasonContains( """ @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") evaluated to false"""); } } DisabledIfEnvironmentVariableConditionTests.java000066400000000000000000000107311455764576500414740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.DisabledIfEnvironmentVariableIntegrationTests.ENIGMA; import static org.junit.jupiter.api.condition.DisabledIfEnvironmentVariableIntegrationTests.KEY1; import static org.junit.jupiter.api.condition.DisabledIfEnvironmentVariableIntegrationTests.KEY2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DisabledIfEnvironmentVariableCondition}. * *

Note that test method names MUST match the test method names in * {@link DisabledIfEnvironmentVariableIntegrationTests}. * * @since 5.1 */ class DisabledIfEnvironmentVariableConditionTests extends AbstractExecutionConditionTests { /** * Stubbed subclass of {@link DisabledIfEnvironmentVariableCondition}. */ private ExecutionCondition condition = new DisabledIfEnvironmentVariableCondition() { @Override protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } }; @Override protected ExecutionCondition getExecutionCondition() { return this.condition; } @Override protected Class getTestClass() { return DisabledIfEnvironmentVariableIntegrationTests.class; } /** * @see DisabledIfEnvironmentVariableIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @DisabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#blankNamedAttribute() */ @Test void blankNamedAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'named' attribute must not be blank"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#blankMatchesAttribute() */ @Test void blankMatchesAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'matches' attribute must not be blank"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableMatchesExactly() */ @Test void disabledBecauseEnvironmentVariableMatchesExactly() { evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); assertCustomDisabledReasonIs("That's an enigma"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableForComposedAnnotationMatchesExactly() */ @Test void disabledBecauseEnvironmentVariableForComposedAnnotationMatchesExactly() { this.condition = new DisabledIfEnvironmentVariableCondition() { @Override protected String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } }; evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableMatchesPattern() */ @Test void disabledBecauseEnvironmentVariableMatchesPattern() { evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#enabledBecauseEnvironmentVariableDoesNotMatch() */ @Test void enabledBecauseEnvironmentVariableDoesNotMatch() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @DisabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see DisabledIfEnvironmentVariableIntegrationTests#enabledBecauseEnvironmentVariableDoesNotExist() */ @Test void enabledBecauseEnvironmentVariableDoesNotExist() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @DisabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } } DisabledIfEnvironmentVariableIntegrationTests.java000066400000000000000000000053551455764576500420370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledIfEnvironmentVariable}. * * @since 5.1 */ @Disabled("Disabled since the required environment variables are not set") // Tests (except those with intentional configuration errors) will pass if you set // the following environment variables: // DisabledIfEnvironmentVariableTests.key1 = enigma // DisabledIfEnvironmentVariableTests.key2 = enigma class DisabledIfEnvironmentVariableIntegrationTests { static final String KEY1 = "DisabledIfEnvironmentVariableTests.key1"; static final String KEY2 = "DisabledIfEnvironmentVariableTests.key2"; static final String ENIGMA = "enigma"; static final String BOGUS = "bogus"; @Test void enabledBecauseAnnotationIsNotPresent() { } @Test @DisabledIfEnvironmentVariable(named = " ", matches = ENIGMA) void blankNamedAttribute() { } @Test @DisabledIfEnvironmentVariable(named = KEY1, matches = " ") void blankMatchesAttribute() { } @Test @DisabledIfEnvironmentVariable(named = KEY1, matches = ENIGMA, disabledReason = "That's an enigma") void disabledBecauseEnvironmentVariableMatchesExactly() { fail("should be disabled"); } @Test @DisabledIfEnvironmentVariable(named = KEY1, matches = BOGUS) @CustomDisabled void disabledBecauseEnvironmentVariableForComposedAnnotationMatchesExactly() { fail("should be disabled"); } @Test @DisabledIfEnvironmentVariable(named = KEY1, matches = ".*e.+gma$") void disabledBecauseEnvironmentVariableMatchesPattern() { fail("should be disabled"); } @Test @DisabledIfEnvironmentVariable(named = KEY1, matches = BOGUS) void enabledBecauseEnvironmentVariableDoesNotMatch() { assertNotEquals(BOGUS, System.getenv(KEY1)); } @Test @DisabledIfEnvironmentVariable(named = BOGUS, matches = "doesn't matter") void enabledBecauseEnvironmentVariableDoesNotExist() { assertNull(System.getenv(BOGUS)); } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @DisabledIfEnvironmentVariable(named = KEY2, matches = ENIGMA) @interface CustomDisabled { } } DisabledIfIntegrationTests.java000066400000000000000000000044531455764576500361420ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledIf}. * * @since 5.7 */ public class DisabledIfIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @DisabledIf(value = "staticMethodThatReturnsTrue", disabledReason = "Disabled for some reason") void disabledBecauseStaticConditionMethodReturnsTrue() { fail("Should be disabled"); } @Test @DisabledIf("staticMethodThatReturnsFalse") void enabledBecauseStaticConditionMethodReturnsFalse() { } @Test @DisabledIf("methodThatReturnsTrue") void disabledBecauseConditionMethodReturnsTrue() { fail("Should be disabled"); } @Test @DisabledIf("methodThatReturnsFalse") void enabledBecauseConditionMethodReturnsFalse() { } @Test @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") void disabledBecauseStaticExternalConditionMethodReturnsTrue() { fail("Should be disabled"); } @Test @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") void enabledBecauseStaticExternalConditionMethodReturnsFalse() { } @Nested @DisabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") class ConditionallyDisabledClass { @Test void disabledBecauseConditionMethodReturnsTrue() { fail("Should be disabled"); } } // ------------------------------------------------------------------------- @SuppressWarnings("unused") private static boolean staticMethodThatReturnsTrue() { return true; } @SuppressWarnings("unused") private static boolean staticMethodThatReturnsFalse() { return false; } @SuppressWarnings("unused") private boolean methodThatReturnsTrue() { return true; } @SuppressWarnings("unused") private boolean methodThatReturnsFalse() { return false; } } DisabledIfSystemPropertyConditionTests.java000066400000000000000000000076041455764576500405600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DisabledIfSystemPropertyCondition}. * *

Note that test method names MUST match the test method names in * {@link DisabledIfSystemPropertyIntegrationTests}. * * @since 5.1 */ class DisabledIfSystemPropertyConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new DisabledIfSystemPropertyCondition(); } @Override protected Class getTestClass() { return DisabledIfSystemPropertyIntegrationTests.class; } @BeforeAll static void setSystemProperties() { DisabledIfSystemPropertyIntegrationTests.setSystemProperties(); } @AfterAll static void clearSystemProperties() { DisabledIfSystemPropertyIntegrationTests.clearSystemProperties(); } /** * @see DisabledIfSystemPropertyIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("No @DisabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see DisabledIfSystemPropertyIntegrationTests#blankNamedAttribute() */ @Test void blankNamedAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'named' attribute must not be blank"); } /** * @see DisabledIfSystemPropertyIntegrationTests#blankMatchesAttribute() */ @Test void blankMatchesAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'matches' attribute must not be blank"); } /** * @see DisabledIfSystemPropertyIntegrationTests#disabledBecauseSystemPropertyMatchesExactly() */ @Test void disabledBecauseSystemPropertyMatchesExactly() { evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); assertCustomDisabledReasonIs("That's an enigma"); } /** * @see DisabledIfSystemPropertyIntegrationTests#disabledBecauseSystemPropertyForComposedAnnotationMatchesExactly() */ @Test void disabledBecauseSystemPropertyForComposedAnnotationMatchesExactly() { evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); } /** * @see DisabledIfSystemPropertyIntegrationTests#disabledBecauseSystemPropertyMatchesPattern() */ @Test void disabledBecauseSystemPropertyMatchesPattern() { evaluateCondition(); assertDisabled(); assertReasonContains("matches regular expression"); } /** * @see DisabledIfSystemPropertyIntegrationTests#enabledBecauseSystemPropertyDoesNotMatch() */ @Test void enabledBecauseSystemPropertyDoesNotMatch() { evaluateCondition(); assertEnabled(); assertReasonContains("No @DisabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see DisabledIfSystemPropertyIntegrationTests#enabledBecauseSystemPropertyDoesNotExist() */ @Test void enabledBecauseSystemPropertyDoesNotExist() { evaluateCondition(); assertEnabled(); assertReasonContains("No @DisabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } } DisabledIfSystemPropertyIntegrationTests.java000066400000000000000000000056051455764576500411140ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledIfSystemProperty}. * * @since 5.1 */ class DisabledIfSystemPropertyIntegrationTests { private static final String KEY1 = "DisabledIfSystemPropertyTests.key1"; private static final String KEY2 = "DisabledIfSystemPropertyTests.key2"; private static final String ENIGMA = "enigma"; private static final String BOGUS = "bogus"; @BeforeAll static void setSystemProperties() { System.setProperty(KEY1, ENIGMA); System.setProperty(KEY2, ENIGMA); } @AfterAll static void clearSystemProperties() { System.clearProperty(KEY1); System.clearProperty(KEY2); } @Test void enabledBecauseAnnotationIsNotPresent() { // no-op } @Test @Disabled("Only used in a unit test via reflection") @DisabledIfSystemProperty(named = " ", matches = ENIGMA) void blankNamedAttribute() { fail("should be disabled"); } @Test @Disabled("Only used in a unit test via reflection") @DisabledIfSystemProperty(named = KEY1, matches = " ") void blankMatchesAttribute() { fail("should be disabled"); } @Test @DisabledIfSystemProperty(named = KEY1, matches = ENIGMA, disabledReason = "That's an enigma") void disabledBecauseSystemPropertyMatchesExactly() { fail("should be disabled"); } @Test @DisabledIfSystemProperty(named = KEY1, matches = BOGUS) @CustomDisabled void disabledBecauseSystemPropertyForComposedAnnotationMatchesExactly() { fail("should be disabled"); } @Test @DisabledIfSystemProperty(named = KEY1, matches = ".*e.+gma$") void disabledBecauseSystemPropertyMatchesPattern() { fail("should be disabled"); } @Test @DisabledIfSystemProperty(named = KEY1, matches = BOGUS) void enabledBecauseSystemPropertyDoesNotMatch() { assertNotEquals(BOGUS, System.getProperty(KEY1)); } @Test @DisabledIfSystemProperty(named = BOGUS, matches = "doesn't matter") void enabledBecauseSystemPropertyDoesNotExist() { assertNull(System.getProperty(BOGUS)); } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @DisabledIfSystemProperty(named = KEY2, matches = ENIGMA) @interface CustomDisabled { } } DisabledOnJreConditionTests.java000066400000000000000000000140031455764576500362540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DisabledOnJreCondition}. * *

Note that test method names MUST match the test method names in * {@link DisabledOnJreIntegrationTests}. * * @since 5.1 */ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new DisabledOnJreCondition(); } @Override protected Class getTestClass() { return DisabledOnJreIntegrationTests.class; } /** * @see DisabledOnJreIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@DisabledOnJre is not present"); } /** * @see DisabledOnJreIntegrationTests#missingJreDeclaration() */ @Test void missingJreDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("You must declare at least one JRE"); } /** * @see DisabledOnJreIntegrationTests#disabledOnAllJavaVersions() */ @Test void disabledOnAllJavaVersions() { evaluateCondition(); assertDisabledOnCurrentJreIf(true); assertCustomDisabledReasonIs("Disabled on every JRE"); } /** * @see DisabledOnJreIntegrationTests#java8() */ @Test void java8() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava8()); } /** * @see DisabledOnJreIntegrationTests#java9() */ @Test void java9() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava9()); } /** * @see DisabledOnJreIntegrationTests#java10() */ @Test void java10() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava10()); } /** * @see DisabledOnJreIntegrationTests#java11() */ @Test void java11() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava11()); } /** * @see DisabledOnJreIntegrationTests#java12() */ @Test void java12() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava12()); } /** * @see DisabledOnJreIntegrationTests#java13() */ @Test void java13() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava13()); } /** * @see DisabledOnJreIntegrationTests#java14() */ @Test void java14() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava14()); } /** * @see DisabledOnJreIntegrationTests#java15() */ @Test void java15() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava15()); } /** * @see DisabledOnJreIntegrationTests#java16() */ @Test void java16() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava16()); } /** * @see DisabledOnJreIntegrationTests#java17() */ @Test void java17() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava17()); } /** * @see DisabledOnJreIntegrationTests#java18() */ @Test void java18() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava18()); } /** * @see DisabledOnJreIntegrationTests#java19() */ @Test void java19() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava19()); } /** * @see DisabledOnJreIntegrationTests#java20() */ @Test void java20() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava20()); } /** * @see DisabledOnJreIntegrationTests#java21() */ @Test void java21() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava21()); } /** * @see DisabledOnJreIntegrationTests#java22() */ @Test void java22() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava22()); } /** * @see DisabledOnJreIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertDisabledOnCurrentJreIf( !(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22())); } private void assertDisabledOnCurrentJreIf(boolean condition) { if (condition) { assertDisabled(); assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); } else { assertEnabled(); assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); } } } DisabledOnJreIntegrationTests.java000066400000000000000000000114741455764576500366220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import static org.junit.jupiter.api.condition.JRE.JAVA_10; import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_12; import static org.junit.jupiter.api.condition.JRE.JAVA_13; import static org.junit.jupiter.api.condition.JRE.JAVA_14; import static org.junit.jupiter.api.condition.JRE.JAVA_15; import static org.junit.jupiter.api.condition.JRE.JAVA_16; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; import static org.junit.jupiter.api.condition.JRE.JAVA_22; import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.JAVA_9; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledOnJre}. * * @since 5.1 */ class DisabledOnJreIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @DisabledOnJre({}) void missingJreDeclaration() { } @Test @DisabledOnJre(value = { JAVA_8, JAVA_9, JAVA_10, JAVA_11, JAVA_12, JAVA_13, JAVA_14, JAVA_15, JAVA_16, JAVA_17, JAVA_18, JAVA_19, JAVA_20, JAVA_21, JAVA_22, OTHER }, disabledReason = "Disabled on every JRE") void disabledOnAllJavaVersions() { fail("should be disabled"); } @Test @DisabledOnJre(JAVA_8) void java8() { assertFalse(onJava8()); } @Test @DisabledOnJre(JAVA_9) void java9() { assertFalse(onJava9()); } @Test @DisabledOnJre(JAVA_10) void java10() { assertFalse(onJava10()); } @Test @DisabledOnJre(JAVA_11) void java11() { assertFalse(onJava11()); } @Test @DisabledOnJre(JAVA_12) void java12() { assertFalse(onJava12()); } @Test @DisabledOnJre(JAVA_13) void java13() { assertFalse(onJava13()); } @Test @DisabledOnJre(JAVA_14) void java14() { assertFalse(onJava14()); } @Test @DisabledOnJre(JAVA_15) void java15() { assertFalse(onJava15()); } @Test @DisabledOnJre(JAVA_16) void java16() { assertFalse(onJava16()); } @Test @DisabledOnJre(JAVA_17) void java17() { assertFalse(onJava17()); } @Test @DisabledOnJre(JAVA_18) void java18() { assertFalse(onJava18()); } @Test @DisabledOnJre(JAVA_19) void java19() { assertFalse(onJava19()); } @Test @DisabledOnJre(JAVA_20) void java20() { assertFalse(onJava20()); } @Test @DisabledOnJre(JAVA_21) void java21() { assertFalse(onJava21()); } @Test @DisabledOnJre(JAVA_22) void java22() { assertFalse(onJava22()); } @Test @DisabledOnJre(OTHER) void other() { assertTrue( onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22()); } } DisabledOnOsConditionTests.java000066400000000000000000000154701455764576500361260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onAix; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onArchitecture; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onFreebsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onLinux; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onMac; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onOpenbsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onSolaris; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onWindows; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DisabledOnOsCondition}. * *

Note that test method names MUST match the test method names in * {@link DisabledOnOsIntegrationTests}. * * @since 5.1 */ class DisabledOnOsConditionTests extends AbstractExecutionConditionTests { private static final String OS_NAME = System.getProperty("os.name"); private static final String ARCH = System.getProperty("os.arch"); @Override protected ExecutionCondition getExecutionCondition() { return new DisabledOnOsCondition(); } @Override protected Class getTestClass() { return DisabledOnOsIntegrationTests.class; } /** * @see DisabledOnOsIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@DisabledOnOs is not present"); } /** * @see DisabledOnOsIntegrationTests#missingOsAndArchitectureDeclaration() */ @Test void missingOsAndArchitectureDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("You must declare at least one OS or architecture"); } /** * @see DisabledOnOsIntegrationTests#disabledOnEveryOs() */ @Test void disabledOnEveryOs() { evaluateCondition(); assertDisabled(); assertReasonContains(String.format("Disabled on operating system: %s ==> Disabled on every OS", OS_NAME)); } /** * @see DisabledOnOsIntegrationTests#aix() */ @Test void aix() { evaluateCondition(); assertDisabledOnCurrentOsIf(onAix()); } /** * @see DisabledOnOsIntegrationTests#freebsd() */ @Test void freebsd() { evaluateCondition(); assertDisabledOnCurrentOsIf(onFreebsd()); } /** * @see DisabledOnOsIntegrationTests#linux() */ @Test void linux() { evaluateCondition(); assertDisabledOnCurrentOsIf(onLinux()); } /** * @see DisabledOnOsIntegrationTests#macOs() */ @Test void macOs() { evaluateCondition(); assertDisabledOnCurrentOsIf(onMac()); } /** * @see DisabledOnOsIntegrationTests#macOsWithComposedAnnotation() */ @Test void macOsWithComposedAnnotation() { evaluateCondition(); assertDisabledOnCurrentOsIf(onMac()); } /** * @see DisabledOnOsIntegrationTests#openbsd() */ @Test void openbsd() { evaluateCondition(); assertDisabledOnCurrentOsIf(onOpenbsd()); } /** * @see DisabledOnOsIntegrationTests#windows() */ @Test void windows() { evaluateCondition(); assertDisabledOnCurrentOsIf(onWindows()); } /** * @see DisabledOnOsIntegrationTests#solaris() */ @Test void solaris() { evaluateCondition(); assertDisabledOnCurrentOsIf(onSolaris()); } /** * @see DisabledOnOsIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertDisabledOnCurrentOsIf( !(onAix() || onFreebsd() || onLinux() || onMac() || onOpenbsd() || onSolaris() || onWindows())); } /** * @see DisabledOnOsIntegrationTests#architectureX86_64() */ @Test void architectureX86_64() { evaluateCondition(); assertDisabledOnCurrentArchitectureIf(onArchitecture("x86_64")); } /** * @see DisabledOnOsIntegrationTests#architectureAarch64() */ @Test void architectureAarch64() { evaluateCondition(); assertDisabledOnCurrentArchitectureIf(onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithMacOs() */ @Test void architectureX86_64WithMacOs() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onMac() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithWindows() */ @Test void architectureX86_64WithWindows() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onWindows() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithLinux() */ @Test void architectureX86_64WithLinux() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onLinux() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithMacOs() */ @Test void aarch64WithMacOs() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onMac() && onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithWindows() */ @Test void aarch64WithWindows() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onWindows() && onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithLinux() */ @Test void aarch64WithLinux() { evaluateCondition(); assertDisabledOnCurrentOsAndArchitectureIf(onLinux() && onArchitecture("aarch64")); } private void assertDisabledOnCurrentOsIf(boolean condition) { if (condition) { assertDisabled(); assertReasonContains(String.format("Disabled on operating system: %s", OS_NAME)); } else { assertEnabled(); assertReasonContains(String.format("Enabled on operating system: %s", OS_NAME)); } } private void assertDisabledOnCurrentArchitectureIf(boolean condition) { if (condition) { assertDisabled(); assertReasonContains(String.format("Disabled on architecture: %s", ARCH)); } else { assertEnabled(); assertReasonContains(String.format("Enabled on architecture: %s", ARCH)); } } private void assertDisabledOnCurrentOsAndArchitectureIf(boolean condition) { if (condition) { assertDisabled(); assertReasonContains(String.format("Disabled on operating system: %s (%s)", OS_NAME, ARCH)); } else { assertEnabled(); assertReasonContains(String.format("Enabled on operating system: %s (%s)", OS_NAME, ARCH)); } } } DisabledOnOsIntegrationTests.java000066400000000000000000000110001455764576500364440ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onAix; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onArchitecture; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onFreebsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onLinux; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onMac; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onOpenbsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onSolaris; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onWindows; import static org.junit.jupiter.api.condition.OS.AIX; import static org.junit.jupiter.api.condition.OS.FREEBSD; import static org.junit.jupiter.api.condition.OS.LINUX; import static org.junit.jupiter.api.condition.OS.MAC; import static org.junit.jupiter.api.condition.OS.OPENBSD; import static org.junit.jupiter.api.condition.OS.OTHER; import static org.junit.jupiter.api.condition.OS.SOLARIS; import static org.junit.jupiter.api.condition.OS.WINDOWS; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link DisabledOnOs}. * * @since 5.1 */ class DisabledOnOsIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @DisabledOnOs({}) void missingOsAndArchitectureDeclaration() { } @Test @DisabledOnOs(value = { AIX, FREEBSD, LINUX, MAC, OPENBSD, WINDOWS, SOLARIS, OTHER }, disabledReason = "Disabled on every OS") void disabledOnEveryOs() { fail("should be disabled"); } @Test @DisabledOnOs(AIX) void aix() { assertFalse(onAix()); } @Test @DisabledOnOs(FREEBSD) void freebsd() { assertFalse(onFreebsd()); } @Test @DisabledOnOs(LINUX) void linux() { assertFalse(onLinux()); } @Test @DisabledOnOs(MAC) void macOs() { assertFalse(onMac()); } @Test @DisabledOnMac void macOsWithComposedAnnotation() { assertFalse(onMac()); } @Test @DisabledOnOs(OPENBSD) void openbsd() { assertFalse(onOpenbsd()); } @Test @DisabledOnOs(WINDOWS) void windows() { assertFalse(onWindows()); } @Test @DisabledOnOs(SOLARIS) void solaris() { assertFalse(onSolaris()); } @Test @DisabledOnOs(OTHER) void other() { assertTrue(onAix() || onFreebsd() || onLinux() || onMac() || onOpenbsd() || onSolaris() || onWindows()); } @Test @DisabledOnOs(architectures = "x86_64") void architectureX86_64() { assertFalse(onArchitecture("x_86_64")); } @Test @DisabledOnOs(architectures = "aarch64") void architectureAarch64() { assertFalse(onArchitecture("aarch64")); } @Test @DisabledOnOs(value = MAC, architectures = "x86_64") void architectureX86_64WithMacOs() { assertFalse(onMac() && onArchitecture("x_86_64")); } @Test @DisabledOnOs(value = WINDOWS, architectures = "x86_64") void architectureX86_64WithWindows() { assertFalse(onWindows() && onArchitecture("x86_64")); } @Test @DisabledOnOs(value = LINUX, architectures = "x86_64") void architectureX86_64WithLinux() { assertFalse(onLinux() && onArchitecture("x86_64")); } @Test @DisabledOnOs(value = MAC, architectures = "aarch64") void aarch64WithMacOs() { assertFalse(onMac() && onArchitecture("aarch64")); } @Test @DisabledOnOs(value = WINDOWS, architectures = "aarch64") void aarch64WithWindows() { assertFalse(onWindows() && onArchitecture("aarch64")); } @Test @DisabledOnOs(value = LINUX, architectures = "aarch64") void aarch64WithLinux() { assertFalse(onLinux() && onArchitecture("aarch64")); } // ------------------------------------------------------------------------- @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @DisabledOnOs(MAC) @interface DisabledOnMac { } } EnabledForJreRangeConditionTests.java000066400000000000000000000105141455764576500372310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link EnabledForJreRange}. * *

Note that test method names MUST match the test method names in * {@link EnabledForJreRangeIntegrationTests}. * * @since 5.6 */ class EnabledForJreRangeConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new EnabledForJreRangeCondition(); } @Override protected Class getTestClass() { return EnabledForJreRangeIntegrationTests.class; } /** * @see EnabledForJreRangeIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@EnabledForJreRange is not present"); } /** * @see EnabledForJreRangeIntegrationTests#defaultValues() */ @Test void defaultValues() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// .withMessageContaining("You must declare a non-default value for min or max in @EnabledForJreRange"); } /** * @see EnabledForJreRangeIntegrationTests#java17() */ @Test void java17() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava17()); } /** * @see EnabledForJreRangeIntegrationTests#java18to19() */ @Test void java18to19() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava18() || onJava19()); } /** * @see EnabledForJreRangeIntegrationTests#javaMax18() */ @Test void javaMax18() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); } /** * @see EnabledForJreRangeIntegrationTests#javaMin18() */ @Test void javaMin18() { evaluateCondition(); assertEnabledOnCurrentJreIf(!(onJava17())); } /** * @see EnabledForJreRangeIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertEnabledOnCurrentJreIf( !(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22())); } private void assertEnabledOnCurrentJreIf(boolean condition) { if (condition) { assertEnabled(); assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); } else { assertDisabled(); assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); } } } EnabledForJreRangeIntegrationTests.java000066400000000000000000000066651455764576500376020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledForJreRange}. * * @since 5.6 */ class EnabledForJreRangeIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @EnabledForJreRange void defaultValues() { fail("should result in a configuration exception"); } @Test @EnabledForJreRange(min = JAVA_17, max = JAVA_17) void java17() { assertTrue(onJava17()); } @Test @EnabledForJreRange(min = JAVA_18, max = JAVA_19) void java18to19() { assertTrue(onJava18() || onJava19()); assertFalse(onJava17()); } @Test @EnabledForJreRange(max = JAVA_18) void javaMax18() { assertTrue(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); assertFalse(onJava19()); } @Test @EnabledForJreRange(min = JAVA_18) void javaMin18() { assertTrue(onJava18() || onJava19() || onJava20() || onJava21() || onJava22()); assertFalse(onJava17()); } @Test @EnabledForJreRange(min = OTHER, max = OTHER) void other() { assertFalse( onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22()); } } EnabledIfConditionClassLoaderTests.java000066400000000000000000000051311455764576500375370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; /** * Tests for {@link EnabledIfCondition} using custom {@link ClassLoader} arrangements. * * @since 5.10 */ public class EnabledIfConditionClassLoaderTests { @Test // No need to introduce a "disabled" version of this test, since it would simply be the // logical inverse of this method and would therefore not provide any further benefit. void enabledWithStaticMethodInTypeFromDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(getClass(), StaticConditionMethods.class)) { var testClass = testClassLoader.loadClass(getClass().getName()); assertThat(testClass.getClassLoader()).isSameAs(testClassLoader); ExtensionContext context = mock(); Method annotatedMethod = ReflectionUtils.findMethod(getClass(), "enabledMethod").get(); when(context.getElement()).thenReturn(Optional.of(annotatedMethod)); doReturn(testClass).when(context).getRequiredTestClass(); EnabledIfCondition condition = new EnabledIfCondition(); ConditionEvaluationResult result = condition.evaluateExecutionCondition(context); assertThat(result).isNotNull(); assertThat(result.isDisabled()).isFalse(); Method conditionMethod = condition.getConditionMethod( "org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue", context); assertThat(conditionMethod).isNotNull(); Class declaringClass = conditionMethod.getDeclaringClass(); assertThat(declaringClass.getClassLoader()).isSameAs(testClassLoader); assertThat(declaringClass.getName()).isEqualTo(StaticConditionMethods.class.getName()); assertThat(declaringClass).isNotEqualTo(StaticConditionMethods.class); } } @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") private void enabledMethod() { } } EnabledIfConditionTests.java000066400000000000000000000057461455764576500354360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; /** * Unit tests for {@link EnabledIf}. * *

Note that test method names MUST match the test method names in * {@link EnabledIfIntegrationTests}. * * @since 5.7 */ public class EnabledIfConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new EnabledIfCondition(); } @Override protected Class getTestClass() { return EnabledIfIntegrationTests.class; } /** * @see EnabledIfIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@EnabledIf is not present"); } /** * @see EnabledIfIntegrationTests#enabledBecauseStaticConditionMethodReturnsTrue() */ @Test void enabledBecauseStaticConditionMethodReturnsTrue() { evaluateCondition(); assertEnabled(); assertReasonContains(""" @EnabledIf("staticMethodThatReturnsTrue") evaluated to true"""); } /** * @see EnabledIfIntegrationTests#disabledBecauseStaticConditionMethodReturnsFalse() */ @Test void disabledBecauseStaticConditionMethodReturnsFalse() { evaluateCondition(); assertDisabled(); assertReasonContains("Disabled for some reason"); } /** * @see EnabledIfIntegrationTests#enabledBecauseConditionMethodReturnsTrue() */ @Test void enabledBecauseConditionMethodReturnsTrue() { evaluateCondition(); assertEnabled(); assertReasonContains(""" @EnabledIf("methodThatReturnsTrue") evaluated to true"""); } /** * @see EnabledIfIntegrationTests#disabledBecauseConditionMethodReturnsFalse() */ @Test void disabledBecauseConditionMethodReturnsFalse() { evaluateCondition(); assertDisabled(); assertReasonContains(""" @EnabledIf("methodThatReturnsFalse") evaluated to false"""); } /** * @see EnabledIfIntegrationTests.ExternalConditionMethod#enabledBecauseStaticExternalConditionMethodReturnsTrue() */ @Test void enabledBecauseStaticExternalConditionMethodReturnsTrue() { evaluateCondition(); assertEnabled(); assertReasonContains(""" @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") evaluated to true"""); } /** * @see EnabledIfIntegrationTests.ExternalConditionMethod#disabledBecauseStaticExternalConditionMethodReturnsFalse() */ @Test void disabledBecauseStaticExternalConditionMethodReturnsFalse() { evaluateCondition(); assertDisabled(); assertReasonContains( """ @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") evaluated to false"""); } } EnabledIfEnvironmentVariableConditionTests.java000066400000000000000000000121261455764576500413170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.BOGUS; import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.ENIGMA; import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.KEY1; import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.KEY2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link EnabledIfEnvironmentVariableCondition}. * *

Note that test method names MUST match the test method names in * {@link EnabledIfEnvironmentVariableIntegrationTests}. * * @since 5.1 */ class EnabledIfEnvironmentVariableConditionTests extends AbstractExecutionConditionTests { /** * Stubbed subclass of {@link EnabledIfEnvironmentVariableCondition}. */ private ExecutionCondition condition = new EnabledIfEnvironmentVariableCondition() { @Override protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } }; @Override protected ExecutionCondition getExecutionCondition() { return condition; } @Override protected Class getTestClass() { return EnabledIfEnvironmentVariableIntegrationTests.class; } /** * @see EnabledIfEnvironmentVariableIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @EnabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#blankNamedAttribute() */ @Test void blankNamedAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'named' attribute must not be blank"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#blankMatchesAttribute() */ @Test void blankMatchesAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'matches' attribute must not be blank"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#enabledBecauseEnvironmentVariableMatchesExactly() */ @Test void enabledBecauseEnvironmentVariableMatchesExactly() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @EnabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#enabledBecauseBothEnvironmentVariablesMatchExactly() */ @Test void enabledBecauseBothEnvironmentVariablesMatchExactly() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override protected String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } }; evaluateCondition(); assertEnabled(); assertReasonContains( "No @EnabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#enabledBecauseEnvironmentVariableMatchesPattern() */ @Test void enabledBecauseEnvironmentVariableMatchesPattern() { evaluateCondition(); assertEnabled(); assertReasonContains( "No @EnabledIfEnvironmentVariable conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableDoesNotMatch() */ @Test void disabledBecauseEnvironmentVariableDoesNotMatch() { evaluateCondition(); assertDisabled(); assertReasonContains("does not match regular expression"); assertCustomDisabledReasonIs("Not bogus"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableForComposedAnnotationDoesNotMatch() */ @Test void disabledBecauseEnvironmentVariableForComposedAnnotationDoesNotMatch() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : KEY2.equals(name) ? BOGUS : null; } }; evaluateCondition(); assertDisabled(); assertReasonContains("does not match regular expression"); } /** * @see EnabledIfEnvironmentVariableIntegrationTests#disabledBecauseEnvironmentVariableDoesNotExist() */ @Test void disabledBecauseEnvironmentVariableDoesNotExist() { evaluateCondition(); assertDisabled(); assertReasonContains("does not exist"); } } EnabledIfEnvironmentVariableIntegrationTests.java000066400000000000000000000057451455764576500416650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledIfEnvironmentVariable}. * * @since 5.1 */ @Disabled("Disabled since the required environment variables are not set") // Tests (except those with intentional configuration errors) will pass if you set // the following environment variables: // EnabledIfEnvironmentVariableTests.key1 = enigma // EnabledIfEnvironmentVariableTests.key2 = enigma class EnabledIfEnvironmentVariableIntegrationTests { static final String KEY1 = "EnabledIfEnvironmentVariableTests.key1"; static final String KEY2 = "EnabledIfEnvironmentVariableTests.key2"; static final String ENIGMA = "enigma"; static final String PUZZLE = "puzzle"; static final String BOGUS = "bogus"; @Test void enabledBecauseAnnotationIsNotPresent() { } @Test @EnabledIfEnvironmentVariable(named = " ", matches = ENIGMA) void blankNamedAttribute() { } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = " ") void blankMatchesAttribute() { } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = ENIGMA) void enabledBecauseEnvironmentVariableMatchesExactly() { assertEquals(ENIGMA, System.getenv(KEY1)); } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = ENIGMA) @EnabledIfEnvironmentVariable(named = KEY2, matches = ENIGMA) void enabledBecauseBothEnvironmentVariablesMatchExactly() { assertEquals(ENIGMA, System.getenv(KEY1)); assertEquals(ENIGMA, System.getenv(KEY2)); } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = ".*e.+ma$") void enabledBecauseEnvironmentVariableMatchesPattern() { assertEquals(ENIGMA, System.getenv(KEY1)); } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = BOGUS, disabledReason = "Not bogus") void disabledBecauseEnvironmentVariableDoesNotMatch() { fail("should be disabled"); } @Test @EnabledIfEnvironmentVariable(named = KEY1, matches = ENIGMA) @CustomEnabled void disabledBecauseEnvironmentVariableForComposedAnnotationDoesNotMatch() { fail("should be disabled"); } @Test @EnabledIfEnvironmentVariable(named = BOGUS, matches = "doesn't matter") void disabledBecauseEnvironmentVariableDoesNotExist() { fail("should be disabled"); } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @EnabledIfEnvironmentVariable(named = KEY2, matches = PUZZLE) @interface CustomEnabled { } } EnabledIfIntegrationTests.java000066400000000000000000000044441455764576500357650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledIf}. * * @since 5.7 */ public class EnabledIfIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @EnabledIf("staticMethodThatReturnsTrue") void enabledBecauseStaticConditionMethodReturnsTrue() { } @Test @EnabledIf(value = "staticMethodThatReturnsFalse", disabledReason = "Disabled for some reason") void disabledBecauseStaticConditionMethodReturnsFalse() { fail("Should be disabled"); } @Test @EnabledIf("methodThatReturnsTrue") void enabledBecauseConditionMethodReturnsTrue() { } @Test @EnabledIf("methodThatReturnsFalse") void disabledBecauseConditionMethodReturnsFalse() { fail("Should be disabled"); } @Test @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsTrue") void enabledBecauseStaticExternalConditionMethodReturnsTrue() { } @Test @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") void disabledBecauseStaticExternalConditionMethodReturnsFalse() { fail("Should be disabled"); } @Nested @EnabledIf("org.junit.jupiter.api.condition.StaticConditionMethods#returnsFalse") class ConditionallyDisabledClass { @Test void disabledBecauseConditionMethodReturnsFalse() { fail("Should be disabled"); } } // ------------------------------------------------------------------------- @SuppressWarnings("unused") private static boolean staticMethodThatReturnsTrue() { return true; } @SuppressWarnings("unused") private static boolean staticMethodThatReturnsFalse() { return false; } @SuppressWarnings("unused") private boolean methodThatReturnsTrue() { return true; } @SuppressWarnings("unused") private boolean methodThatReturnsFalse() { return false; } } EnabledIfSystemPropertyConditionTests.java000066400000000000000000000100671455764576500404000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link EnabledIfSystemPropertyCondition}. * *

Note that test method names MUST match the test method names in * {@link EnabledIfSystemPropertyIntegrationTests}. * * @since 5.1 */ class EnabledIfSystemPropertyConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new EnabledIfSystemPropertyCondition(); } @Override protected Class getTestClass() { return EnabledIfSystemPropertyIntegrationTests.class; } @BeforeAll static void setSystemProperties() { EnabledIfSystemPropertyIntegrationTests.setSystemProperties(); } @AfterAll static void clearSystemProperties() { EnabledIfSystemPropertyIntegrationTests.clearSystemProperties(); } /** * @see EnabledIfSystemPropertyIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("No @EnabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfSystemPropertyIntegrationTests#blankNamedAttribute() */ @Test void blankNamedAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'named' attribute must not be blank"); } /** * @see EnabledIfSystemPropertyIntegrationTests#blankMatchesAttribute() */ @Test void blankMatchesAttribute() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("The 'matches' attribute must not be blank"); } /** * @see EnabledIfSystemPropertyIntegrationTests#enabledBecauseSystemPropertyMatchesExactly() */ @Test void enabledBecauseSystemPropertyMatchesExactly() { evaluateCondition(); assertEnabled(); assertReasonContains("No @EnabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfSystemPropertyIntegrationTests#enabledBecauseBothSystemPropertiesMatchExactly() */ @Test void enabledBecauseBothSystemPropertiesMatchExactly() { evaluateCondition(); assertEnabled(); assertReasonContains("No @EnabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfSystemPropertyIntegrationTests#enabledBecauseSystemPropertyMatchesPattern() */ @Test void enabledBecauseSystemPropertyMatchesPattern() { evaluateCondition(); assertEnabled(); assertReasonContains("No @EnabledIfSystemProperty conditions resulting in 'disabled' execution encountered"); } /** * @see EnabledIfSystemPropertyIntegrationTests#disabledBecauseSystemPropertyDoesNotMatch() */ @Test void disabledBecauseSystemPropertyDoesNotMatch() { evaluateCondition(); assertDisabled(); assertReasonContains("does not match regular expression"); assertCustomDisabledReasonIs("Not bogus"); } @Test void disabledBecauseSystemPropertyForComposedAnnotationDoesNotMatch() { evaluateCondition(); assertDisabled(); assertReasonContains("does not match regular expression"); } /** * @see EnabledIfSystemPropertyIntegrationTests#disabledBecauseSystemPropertyDoesNotExist() */ @Test void disabledBecauseSystemPropertyDoesNotExist() { evaluateCondition(); assertDisabled(); assertReasonContains("does not exist"); } } EnabledIfSystemPropertyIntegrationTests.java000066400000000000000000000061111455764576500407300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledIfSystemProperty}. * * @since 5.1 */ class EnabledIfSystemPropertyIntegrationTests { private static final String KEY1 = "EnabledIfSystemPropertyTests.key1"; private static final String KEY2 = "EnabledIfSystemPropertyTests.key2"; private static final String ENIGMA = "enigma"; private static final String BOGUS = "bogus"; @BeforeAll static void setSystemProperties() { System.setProperty(KEY1, ENIGMA); System.setProperty(KEY2, ENIGMA); } @AfterAll static void clearSystemProperties() { System.clearProperty(KEY1); System.clearProperty(KEY2); } @Test void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @EnabledIfSystemProperty(named = " ", matches = ENIGMA) void blankNamedAttribute() { fail("should be disabled"); } @Test @Disabled("Only used in a unit test via reflection") @EnabledIfSystemProperty(named = KEY1, matches = " ") void blankMatchesAttribute() { fail("should be disabled"); } @Test @EnabledIfSystemProperty(named = KEY1, matches = ENIGMA) void enabledBecauseSystemPropertyMatchesExactly() { assertEquals(ENIGMA, System.getProperty(KEY1)); } @Test @EnabledIfSystemProperty(named = KEY1, matches = ENIGMA) @EnabledIfSystemProperty(named = KEY2, matches = ENIGMA) void enabledBecauseBothSystemPropertiesMatchExactly() { assertEquals(ENIGMA, System.getProperty(KEY1)); assertEquals(ENIGMA, System.getProperty(KEY2)); } @Test @EnabledIfSystemProperty(named = KEY1, matches = ".*en.+gma$") void enabledBecauseSystemPropertyMatchesPattern() { assertEquals(ENIGMA, System.getProperty(KEY1)); } @Test @EnabledIfSystemProperty(named = KEY1, matches = BOGUS, disabledReason = "Not bogus") void disabledBecauseSystemPropertyDoesNotMatch() { fail("should be disabled"); } @Test @EnabledIfSystemProperty(named = KEY1, matches = ENIGMA) @CustomEnabled void disabledBecauseSystemPropertyForComposedAnnotationDoesNotMatch() { fail("should be disabled"); } @Test @EnabledIfSystemProperty(named = BOGUS, matches = "doesn't matter") void disabledBecauseSystemPropertyDoesNotExist() { fail("should be disabled"); } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @EnabledIfSystemProperty(named = KEY2, matches = BOGUS) @interface CustomEnabled { } } EnabledOnJreConditionTests.java000066400000000000000000000137351455764576500361120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava10; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava11; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava12; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava13; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava14; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava15; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava16; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava17; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava18; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava19; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava20; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava21; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava22; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava8; import static org.junit.jupiter.api.condition.EnabledOnJreIntegrationTests.onJava9; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link EnabledOnJreCondition}. * *

Note that test method names MUST match the test method names in * {@link EnabledOnJreIntegrationTests}. * * @since 5.1 */ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { @Override protected ExecutionCondition getExecutionCondition() { return new EnabledOnJreCondition(); } @Override protected Class getTestClass() { return EnabledOnJreIntegrationTests.class; } /** * @see EnabledOnJreIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@EnabledOnJre is not present"); } /** * @see EnabledOnJreIntegrationTests#missingJreDeclaration() */ @Test void missingJreDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("You must declare at least one JRE"); } /** * @see EnabledOnJreIntegrationTests#enabledOnAllJavaVersions() */ @Test void enabledOnAllJavaVersions() { evaluateCondition(); assertEnabledOnCurrentJreIf(true); } /** * @see EnabledOnJreIntegrationTests#java8() */ @Test void java8() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava8()); } /** * @see EnabledOnJreIntegrationTests#java9() */ @Test void java9() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava9()); } /** * @see EnabledOnJreIntegrationTests#java10() */ @Test void java10() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava10()); } /** * @see EnabledOnJreIntegrationTests#java11() */ @Test void java11() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava11()); } /** * @see EnabledOnJreIntegrationTests#java12() */ @Test void java12() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava12()); } /** * @see EnabledOnJreIntegrationTests#java13() */ @Test void java13() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava13()); } /** * @see EnabledOnJreIntegrationTests#java14() */ @Test void java14() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava14()); } /** * @see EnabledOnJreIntegrationTests#java15() */ @Test void java15() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava15()); } /** * @see EnabledOnJreIntegrationTests#java16() */ @Test void java16() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava16()); } /** * @see EnabledOnJreIntegrationTests#java17() */ @Test void java17() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava17()); } /** * @see EnabledOnJreIntegrationTests#java18() */ @Test void java18() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava18()); } /** * @see EnabledOnJreIntegrationTests#java19() */ @Test void java19() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava19()); } /** * @see EnabledOnJreIntegrationTests#java20() */ @Test void java20() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava20()); } /** * @see EnabledOnJreIntegrationTests#java21() */ @Test void java21() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava21()); } /** * @see EnabledOnJreIntegrationTests#java22() */ @Test void java22() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava22()); } /** * @see EnabledOnJreIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertEnabledOnCurrentJreIf( !(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22())); assertCustomDisabledReasonIs("Disabled on almost every JRE"); } private void assertEnabledOnCurrentJreIf(boolean condition) { if (condition) { assertEnabled(); assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); } else { assertDisabled(); assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); } } } EnabledOnJreIntegrationTests.java000066400000000000000000000111521455764576500364360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.condition.JRE.JAVA_10; import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_12; import static org.junit.jupiter.api.condition.JRE.JAVA_13; import static org.junit.jupiter.api.condition.JRE.JAVA_14; import static org.junit.jupiter.api.condition.JRE.JAVA_15; import static org.junit.jupiter.api.condition.JRE.JAVA_16; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; import static org.junit.jupiter.api.condition.JRE.JAVA_22; import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.JAVA_9; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledOnJre}. * * @since 5.1 */ class EnabledOnJreIntegrationTests { private static final String JAVA_VERSION = System.getProperty("java.version"); @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @EnabledOnJre({}) void missingJreDeclaration() { } @Test @EnabledOnJre({ JAVA_8, JAVA_9, JAVA_10, JAVA_11, JAVA_12, JAVA_13, JAVA_14, JAVA_15, JAVA_16, JAVA_17, JAVA_18, JAVA_19, JAVA_20, JAVA_21, JAVA_22, OTHER }) void enabledOnAllJavaVersions() { } @Test @EnabledOnJre(JAVA_8) void java8() { assertTrue(onJava8()); } @Test @EnabledOnJre(JAVA_9) void java9() { assertTrue(onJava9()); } @Test @EnabledOnJre(JAVA_10) void java10() { assertTrue(onJava10()); } @Test @EnabledOnJre(JAVA_11) void java11() { assertTrue(onJava11()); } @Test @EnabledOnJre(JAVA_12) void java12() { assertTrue(onJava12()); } @Test @EnabledOnJre(JAVA_13) void java13() { assertTrue(onJava13()); } @Test @EnabledOnJre(JAVA_14) void java14() { assertTrue(onJava14()); } @Test @EnabledOnJre(JAVA_15) void java15() { assertTrue(onJava15()); } @Test @EnabledOnJre(JAVA_16) void java16() { assertTrue(onJava16()); } @Test @EnabledOnJre(JAVA_17) void java17() { assertTrue(onJava17()); } @Test @EnabledOnJre(JAVA_18) void java18() { assertTrue(onJava18()); } @Test @EnabledOnJre(JAVA_19) void java19() { assertTrue(onJava19()); } @Test @EnabledOnJre(JAVA_20) void java20() { assertTrue(onJava20()); } @Test @EnabledOnJre(JAVA_21) void java21() { assertTrue(onJava21()); } @Test @EnabledOnJre(JAVA_22) void java22() { assertTrue(onJava22()); } @Test @EnabledOnJre(value = OTHER, disabledReason = "Disabled on almost every JRE") void other() { assertFalse( onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22()); } static boolean onJava8() { return JAVA_VERSION.startsWith("1.8"); } static boolean onJava9() { return JAVA_VERSION.startsWith("9"); } static boolean onJava10() { return JAVA_VERSION.startsWith("10"); } static boolean onJava11() { return JAVA_VERSION.startsWith("11"); } static boolean onJava12() { return JAVA_VERSION.startsWith("12"); } static boolean onJava13() { return JAVA_VERSION.startsWith("13"); } static boolean onJava14() { return JAVA_VERSION.startsWith("14"); } static boolean onJava15() { return JAVA_VERSION.startsWith("15"); } static boolean onJava16() { return JAVA_VERSION.startsWith("16"); } static boolean onJava17() { return JAVA_VERSION.startsWith("17"); } static boolean onJava18() { return JAVA_VERSION.startsWith("18"); } static boolean onJava19() { return JAVA_VERSION.startsWith("19"); } static boolean onJava20() { return JAVA_VERSION.startsWith("20"); } static boolean onJava21() { return JAVA_VERSION.startsWith("21"); } static boolean onJava22() { return JAVA_VERSION.startsWith("22"); } } EnabledOnOsConditionTests.java000066400000000000000000000153601455764576500357470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onAix; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onArchitecture; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onFreebsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onLinux; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onMac; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onOpenbsd; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onSolaris; import static org.junit.jupiter.api.condition.EnabledOnOsIntegrationTests.onWindows; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link EnabledOnOsCondition}. * *

Note that test method names MUST match the test method names in * {@link EnabledOnOsIntegrationTests}. * * @since 5.1 */ class EnabledOnOsConditionTests extends AbstractExecutionConditionTests { private static final String OS_NAME = System.getProperty("os.name"); private static final String ARCH = System.getProperty("os.arch"); @Override protected ExecutionCondition getExecutionCondition() { return new EnabledOnOsCondition(); } @Override protected Class getTestClass() { return EnabledOnOsIntegrationTests.class; } /** * @see EnabledOnOsIntegrationTests#enabledBecauseAnnotationIsNotPresent() */ @Test void enabledBecauseAnnotationIsNotPresent() { evaluateCondition(); assertEnabled(); assertReasonContains("@EnabledOnOs is not present"); } /** * @see EnabledOnOsIntegrationTests#missingOsAndArchitectureDeclaration() */ @Test void missingOsAndArchitectureDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); assertThat(exception).hasMessageContaining("You must declare at least one OS or architecture"); } /** * @see EnabledOnOsIntegrationTests#enabledOnEveryOs() */ @Test void enabledOnEveryOs() { evaluateCondition(); assertEnabledOnCurrentOsIf(true); } /** * @see EnabledOnOsIntegrationTests#aix() */ @Test void aix() { evaluateCondition(); assertEnabledOnCurrentOsIf(onAix()); } /** * @see EnabledOnOsIntegrationTests#freebsd() */ @Test void freebsd() { evaluateCondition(); assertEnabledOnCurrentOsIf(onFreebsd()); } /** * @see EnabledOnOsIntegrationTests#linux() */ @Test void linux() { evaluateCondition(); assertEnabledOnCurrentOsIf(onLinux()); } /** * @see EnabledOnOsIntegrationTests#macOs() */ @Test void macOs() { evaluateCondition(); assertEnabledOnCurrentOsIf(onMac()); } /** * @see EnabledOnOsIntegrationTests#macOsWithComposedAnnotation() */ @Test void macOsWithComposedAnnotation() { evaluateCondition(); assertEnabledOnCurrentOsIf(onMac()); } /** * @see EnabledOnOsIntegrationTests#openbsd() */ @Test void openbsd() { evaluateCondition(); assertEnabledOnCurrentOsIf(onOpenbsd()); } /** * @see EnabledOnOsIntegrationTests#windows() */ @Test void windows() { evaluateCondition(); assertEnabledOnCurrentOsIf(onWindows()); } /** * @see EnabledOnOsIntegrationTests#solaris() */ @Test void solaris() { evaluateCondition(); assertEnabledOnCurrentOsIf(onSolaris()); } /** * @see EnabledOnOsIntegrationTests#other() */ @Test void other() { evaluateCondition(); assertEnabledOnCurrentOsIf( !(onAix() || onFreebsd() || onLinux() || onMac() || onOpenbsd() || onSolaris() || onWindows())); assertCustomDisabledReasonIs("Disabled on almost every OS"); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64() */ @Test void architectureX86_64() { evaluateCondition(); assertEnabledOnCurrentArchitectureIf(onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#architectureAarch64() */ @Test void architectureAarch64() { evaluateCondition(); assertEnabledOnCurrentArchitectureIf(onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithMacOs() */ @Test void architectureX86_64WithMacOs() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onMac() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithWindows() */ @Test void architectureX86_64WithWindows() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onWindows() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#architectureX86_64WithLinux() */ @Test void architectureX86_64WithLinux() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onLinux() && onArchitecture("x86_64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithMacOs() */ @Test void aarch64WithMacOs() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onMac() && onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithWindows() */ @Test void aarch64WithWindows() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onWindows() && onArchitecture("aarch64")); } /** * @see EnabledOnOsIntegrationTests#aarch64WithLinux() */ @Test void aarch64WithLinux() { evaluateCondition(); assertEnabledOnCurrentOsAndArchitectureIf(onLinux() && onArchitecture("aarch64")); } private void assertEnabledOnCurrentOsIf(boolean condition) { if (condition) { assertEnabled(); assertReasonContains(String.format("Enabled on operating system: %s", OS_NAME)); } else { assertDisabled(); assertReasonContains(String.format("Disabled on operating system: %s", OS_NAME)); } } private void assertEnabledOnCurrentArchitectureIf(boolean condition) { if (condition) { assertEnabled(); assertReasonContains(String.format("Enabled on architecture: %s", ARCH)); } else { assertDisabled(); assertReasonContains(String.format("Disabled on architecture: %s", ARCH)); } } private void assertEnabledOnCurrentOsAndArchitectureIf(boolean condition) { if (condition) { assertEnabled(); assertReasonContains(String.format("Enabled on operating system: %s (%s)", OS_NAME, ARCH)); } else { assertDisabled(); assertReasonContains(String.format("Disabled on operating system: %s (%s)", OS_NAME, ARCH)); } } } EnabledOnOsIntegrationTests.java000066400000000000000000000110771455764576500363050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.condition.OS.AIX; import static org.junit.jupiter.api.condition.OS.FREEBSD; import static org.junit.jupiter.api.condition.OS.LINUX; import static org.junit.jupiter.api.condition.OS.MAC; import static org.junit.jupiter.api.condition.OS.OPENBSD; import static org.junit.jupiter.api.condition.OS.OTHER; import static org.junit.jupiter.api.condition.OS.SOLARIS; import static org.junit.jupiter.api.condition.OS.WINDOWS; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Locale; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link EnabledOnOs}. * * @since 5.1 */ class EnabledOnOsIntegrationTests { private static final String ARCH = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH); private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { } @Test @Disabled("Only used in a unit test via reflection") @EnabledOnOs({}) void missingOsAndArchitectureDeclaration() { } @Test @EnabledOnOs({ AIX, FREEBSD, LINUX, MAC, OPENBSD, WINDOWS, SOLARIS, OTHER }) void enabledOnEveryOs() { } @Test @EnabledOnOs(AIX) void aix() { assertTrue(onAix()); } @Test @EnabledOnOs(FREEBSD) void freebsd() { assertTrue(onFreebsd()); } @Test @EnabledOnOs(LINUX) void linux() { assertTrue(onLinux()); } @Test @EnabledOnOs(MAC) void macOs() { assertTrue(onMac()); } @Test @EnabledOnMac void macOsWithComposedAnnotation() { assertTrue(onMac()); } @Test @EnabledOnOs(OPENBSD) void openbsd() { assertTrue(onOpenbsd()); } @Test @EnabledOnOs(WINDOWS) void windows() { assertTrue(onWindows()); } @Test @EnabledOnOs(SOLARIS) void solaris() { assertTrue(onSolaris()); } @Test @EnabledOnOs(value = OTHER, disabledReason = "Disabled on almost every OS") void other() { assertFalse(onAix() || onFreebsd() || onLinux() || onMac() || onOpenbsd() || onSolaris() || onWindows()); } @Test @EnabledOnOs(architectures = "x86_64") void architectureX86_64() { assertFalse(onArchitecture("x_86_64")); } @Test @EnabledOnOs(architectures = "aarch64") void architectureAarch64() { assertTrue(onArchitecture("aarch64")); } @Test @EnabledOnOs(value = MAC, architectures = "x86_64") void architectureX86_64WithMacOs() { assertTrue(onMac()); assertTrue(onArchitecture("x86_64")); } @Test @EnabledOnOs(value = WINDOWS, architectures = "x86_64") void architectureX86_64WithWindows() { assertTrue(onWindows()); assertTrue(onArchitecture("x86_64")); } @Test @EnabledOnOs(value = LINUX, architectures = "x86_64") void architectureX86_64WithLinux() { assertTrue(onLinux()); assertTrue(onArchitecture("x86_64")); } @Test @EnabledOnOs(value = MAC, architectures = "aarch64") void aarch64WithMacOs() { assertTrue(onMac()); assertTrue(onArchitecture("aarch64")); } @Test @EnabledOnOs(value = WINDOWS, architectures = "aarch64") void aarch64WithWindows() { assertTrue(onWindows()); assertTrue(onArchitecture("aarch64")); } @Test @EnabledOnOs(value = LINUX, architectures = "aarch64") void aarch64WithLinux() { assertTrue(onLinux()); assertTrue(onArchitecture("aarch64")); } static boolean onAix() { return OS_NAME.contains("aix"); } static boolean onArchitecture(String arch) { return ARCH.contains(arch); } static boolean onFreebsd() { return OS_NAME.contains("freebsd"); } static boolean onLinux() { return OS_NAME.contains("linux"); } static boolean onMac() { return OS_NAME.contains("mac"); } static boolean onOpenbsd() { return OS_NAME.contains("openbsd"); } static boolean onSolaris() { return OS_NAME.contains("solaris"); } static boolean onWindows() { return OS_NAME.contains("windows"); } // ------------------------------------------------------------------------- @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @EnabledOnOs(MAC) @interface EnabledOnMac { } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/JRETests.java000066400000000000000000000031431455764576500324420ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; import static org.junit.jupiter.api.condition.JRE.JAVA_22; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Test; /** * Unit tests for {@link JRE} * * @since 5.7 */ public class JRETests { @Test @EnabledOnJre(JAVA_17) void java17() { assertEquals(JAVA_17, JRE.currentVersion()); } @Test @EnabledOnJre(JAVA_18) void java18() { assertEquals(JAVA_18, JRE.currentVersion()); } @Test @EnabledOnJre(JAVA_19) void java19() { assertEquals(JAVA_19, JRE.currentVersion()); } @Test @EnabledOnJre(JAVA_20) void java20() { assertEquals(JAVA_20, JRE.currentVersion()); } @Test @EnabledOnJre(JAVA_21) void java21() { assertEquals(JAVA_21, JRE.currentVersion()); } @Test @EnabledOnJre(JAVA_22) void java22() { assertEquals(JAVA_22, JRE.currentVersion()); } @Test @EnabledOnJre(OTHER) void other() { assertEquals(OTHER, JRE.currentVersion()); } } StaticConditionMethods.java000066400000000000000000000010041455764576500353340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/condition/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; public class StaticConditionMethods { public static boolean returnsTrue() { return true; } public static boolean returnsFalse() { return false; } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/000077500000000000000000000000001455764576500301615ustar00rootroot00000000000000CloseableResourceIntegrationTests.java000066400000000000000000000055431455764576500376040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.reportEntry; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.suppressed; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; public class CloseableResourceIntegrationTests extends AbstractJupiterTestEngineTests { @Test void closesCloseableResourcesInReverseInsertOrder() { executeTestsForClass(TestCase.class).allEvents().reportingEntryPublished() // .assertEventsMatchExactly( // reportEntry(Map.of("3", "closed")), // reportEntry(Map.of("2", "closed")), // reportEntry(Map.of("1", "closed"))); } @ExtendWith(ExtensionContextParameterResolver.class) static class TestCase { @Test void closesCloseableResourcesInExtensionContext(ExtensionContext extensionContext) { ExtensionContext.Store store = extensionContext.getStore(GLOBAL); store.put("foo", reportEntryOnClose(extensionContext, "1")); store.put("bar", reportEntryOnClose(extensionContext, "2")); store.put("baz", reportEntryOnClose(extensionContext, "3")); } private ExtensionContext.Store.CloseableResource reportEntryOnClose(ExtensionContext extensionContext, String key) { return () -> extensionContext.publishReportEntry(Map.of(key, "closed")); } } @Test void exceptionsDuringCloseAreReportedAsSuppressed() { executeTestsForClass(ExceptionInCloseableResourceTestCase.class).testEvents() // .assertEventsMatchLoosely(event( // test(), // finishedWithFailure( // message("Exception in test"), // suppressed(0, message("Exception in onClose"))))); } @ExtendWith(ThrowingOnCloseExtension.class) static class ExceptionInCloseableResourceTestCase { @Test void test() { throw new RuntimeException("Exception in test"); } } static class ThrowingOnCloseExtension implements BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { context.getStore(GLOBAL).put("throwingResource", (ExtensionContext.Store.CloseableResource) () -> { throw new RuntimeException("Exception in onClose"); }); } } } ExecutableInvokerIntegrationTests.java000066400000000000000000000046461455764576500376250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * @since 5.9 */ public class ExecutableInvokerIntegrationTests extends AbstractJupiterTestEngineTests { @Test void invokeConstructorViaExtensionContext() { EngineExecutionResults results = executeTestsForClass(ExecuteConstructorTwiceTestCase.class); assertEquals(1, results.testEvents().succeeded().count()); assertEquals(2, ExecuteConstructorTwiceTestCase.constructorInvocations); } @Test void invokeMethodViaExtensionContext() { EngineExecutionResults results = executeTestsForClass(ExecuteTestsTwiceTestCase.class); assertEquals(1, results.testEvents().succeeded().count()); assertEquals(2, ExecuteTestsTwiceTestCase.testInvocations); } @ExtendWith(ExecuteTestsTwiceExtension.class) static class ExecuteTestsTwiceTestCase { static int testInvocations = 0; @Test void testWithResolvedParameter(TestInfo testInfo) { assertNotNull(testInfo); testInvocations++; } } @ExtendWith(ExecuteConstructorTwiceExtension.class) static class ExecuteConstructorTwiceTestCase { static int constructorInvocations = 0; public ExecuteConstructorTwiceTestCase(TestInfo testInfo) { assertNotNull(testInfo); constructorInvocations++; } @Test void test() { } } static class ExecuteTestsTwiceExtension implements AfterTestExecutionCallback { @Override public void afterTestExecution(ExtensionContext context) { context.getExecutableInvoker() // .invoke(context.getRequiredTestMethod(), context.getRequiredTestInstance()); } } static class ExecuteConstructorTwiceExtension implements BeforeAllCallback { @Override public void beforeAll(ExtensionContext context) throws Exception { context.getExecutableInvoker() // .invoke(context.getRequiredTestClass().getConstructor(TestInfo.class)); } } } ExtensionComposabilityTests.java000066400000000000000000000075711455764576500365150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import static java.util.function.Predicate.not; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.platform.commons.util.FunctionUtils.where; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for extension composability in JUnit Jupiter. * *

The purpose of these tests is to ensure that a concrete extension * (a.k.a., the kitchen sink extension) is able to implement all extension * APIs supported by JUnit Jupiter without any naming conflicts or * ambiguities with regard to method names or method signatures. * * @since 5.0 * @see KitchenSinkExtension */ class ExtensionComposabilityTests { @Test void ensureJupiterExtensionApisAreComposable() { // 1) Find all existing top-level Extension APIs List> extensionApis = ReflectionUtils.findAllClassesInPackage(Extension.class.getPackage().getName(), this::isExtensionApi, name -> true); // 2) Determine which methods we expect the kitchen sink to implement... // @formatter:off List expectedMethods = extensionApis.stream() .map(Class::getDeclaredMethods) .flatMap(Arrays::stream) .filter(not(Method::isSynthetic)) .filter(not(where(Method::getModifiers, Modifier::isStatic))) .collect(toList()); List expectedMethodSignatures = expectedMethods.stream() .map(this::methodSignature) .sorted() .collect(toList()); List expectedMethodNames = expectedMethods.stream() .map(Method::getName) .distinct() .sorted() .collect(toList()); // @formatter:on // 3) Dynamically implement all Extension APIs Object dynamicKitchenSinkExtension = Proxy.newProxyInstance(getClass().getClassLoader(), extensionApis.toArray(Class[]::new), (proxy, method, args) -> null); // 4) Determine what ended up in the kitchen sink... // @formatter:off List actualMethods = Arrays.stream(dynamicKitchenSinkExtension.getClass().getDeclaredMethods()) .filter(ReflectionUtils::isNotStatic) .collect(toList()); List actualMethodSignatures = actualMethods.stream() .map(this::methodSignature) .distinct() .sorted() .collect(toList()); List actualMethodNames = actualMethods.stream() .map(Method::getName) .distinct() .sorted() .collect(toList()); // @formatter:on // 5) Remove methods from java.lang.Object actualMethodSignatures.remove("equals(Object)"); actualMethodSignatures.remove("hashCode()"); actualMethodSignatures.remove("toString()"); actualMethodNames.remove("equals"); actualMethodNames.remove("hashCode"); actualMethodNames.remove("toString"); // 6) Verify our expectations // @formatter:off assertAll( () -> assertThat(actualMethodSignatures).isEqualTo(expectedMethodSignatures), () -> assertThat(actualMethodNames).isEqualTo(expectedMethodNames) ); // @formatter:on } private boolean isExtensionApi(Class candidate) { return candidate.isInterface() && (candidate != Extension.class) && Extension.class.isAssignableFrom(candidate); } private String methodSignature(Method method) { return String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes())); } } KitchenSinkExtension.java000066400000000000000000000107571455764576500350660ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension; import java.util.Optional; import java.util.stream.Stream; /** * Kitchen Sink extension that implements every extension API * supported by JUnit Jupiter. * *

This extension should never actually be registered for any tests. * Rather, its sole purpose is to help ensure (via visual inspection) * that a concrete extension is able to implement all extension APIs * supported by JUnit Jupiter without any naming conflicts or * ambiguities with regard to method names or method signatures. * {@link ExtensionComposabilityTests}, on the other hand, serves * the same purpose in a dynamic and automated fashion. * * @since 5.0 * @see ExtensionComposabilityTests */ // @formatter:off public class KitchenSinkExtension implements // Lifecycle Callbacks BeforeAllCallback, BeforeEachCallback, BeforeTestExecutionCallback, TestExecutionExceptionHandler, AfterTestExecutionCallback, AfterEachCallback, AfterAllCallback, // Lifecycle methods exception handling LifecycleMethodExecutionExceptionHandler, // Dependency Injection TestInstancePreConstructCallback, TestInstanceFactory, TestInstancePostProcessor, TestInstancePreDestroyCallback, ParameterResolver, // Conditional Test Execution ExecutionCondition, // @TestTemplate TestTemplateInvocationContextProvider, // Miscellaneous TestWatcher, InvocationInterceptor // @formatter:on { // --- Lifecycle Callbacks ------------------------------------------------- @Override public void beforeAll(ExtensionContext context) { } @Override public void beforeEach(ExtensionContext context) { } @Override public void beforeTestExecution(ExtensionContext context) { } @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) { } @Override public void afterTestExecution(ExtensionContext context) { } @Override public void afterEach(ExtensionContext context) { } @Override public void afterAll(ExtensionContext context) { } // --- Lifecycle methods exception handling @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) { } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) { } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) { } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) { } // --- Dependency Injection ------------------------------------------------ @Override public void preConstructTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext context) { } @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { return null; } @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { } @Override public void preDestroyTestInstance(ExtensionContext context) { } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return false; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return null; } // --- Conditional Test Execution ------------------------------------------ @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return null; } // --- @TestTemplate ------------------------------------------------------- @Override public boolean supportsTestTemplate(ExtensionContext context) { return false; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return null; } // --- TestWatcher --------------------------------------------------------- @Override public void testDisabled(ExtensionContext context, Optional reason) { } @Override public void testSuccessful(ExtensionContext context) { } @Override public void testAborted(ExtensionContext context, Throwable cause) { } @Override public void testFailed(ExtensionContext context, Throwable cause) { } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/support/000077500000000000000000000000001455764576500316755ustar00rootroot00000000000000TypeBasedParameterResolverTests.java000066400000000000000000000140621455764576500407520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.extension.support; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.6 */ class TypeBasedParameterResolverTests { private final ParameterResolver basicTypeBasedParameterResolver = new BasicTypeBasedParameterResolver(); private final ParameterResolver subClassedBasicTypeBasedParameterResolver = new SubClassedBasicTypeBasedParameterResolver(); private final ParameterResolver parametrizedTypeBasedParameterResolver = new ParameterizedTypeBasedParameterResolver(); @Test void missingTypeTypeBasedParameterResolver() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, MissingTypeTypeBasedParameterResolver::new); assertEquals( "Failed to discover parameter type supported by " + MissingTypeTypeBasedParameterResolver.class.getName() + "; potentially caused by lacking parameterized type in class declaration.", exception.getMessage()); } @Test void supportsParameterForBasicTypes() { Parameter parameter1 = findParameterOfMethod("methodWithBasicTypeParameter", String.class); assertTrue(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); assertTrue(subClassedBasicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); Parameter parameter2 = findParameterOfMethod("methodWithObjectParameter", Object.class); assertFalse(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter2), null)); } @Test void supportsParameterForParameterizedTypes() { Parameter parameter1 = findParameterOfMethod("methodWithParameterizedTypeParameter", Map.class); assertTrue(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); Parameter parameter3 = findParameterOfMethod("methodWithAnotherParameterizedTypeParameter", Map.class); assertFalse(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter3), null)); } @Test void resolve() { ExtensionContext extensionContext = extensionContext(); ParameterContext parameterContext = parameterContext( findParameterOfMethod("methodWithBasicTypeParameter", String.class)); assertEquals("Displaying TestAnnotation", basicTypeBasedParameterResolver.resolveParameter(parameterContext, extensionContext)); Parameter parameter2 = findParameterOfMethod("methodWithParameterizedTypeParameter", Map.class); assertEquals(Map.of("ids", List.of(1, 42)), parametrizedTypeBasedParameterResolver.resolveParameter(parameterContext(parameter2), extensionContext)); } private static ParameterContext parameterContext(Parameter parameter) { ParameterContext parameterContext = mock(); when(parameterContext.getParameter()).thenReturn(parameter); return parameterContext; } private static ExtensionContext extensionContext() { ExtensionContext extensionContext = mock(); when(extensionContext.getDisplayName()).thenReturn("Displaying"); return extensionContext; } private Parameter findParameterOfMethod(String methodName, Class... parameterTypes) { Method method = ReflectionUtils.findMethod(Sample.class, methodName, parameterTypes).get(); return method.getParameters()[0]; } // ------------------------------------------------------------------------- @SuppressWarnings("rawtypes") static class MissingTypeTypeBasedParameterResolver extends TypeBasedParameterResolver { @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return "enigma"; } } static class BasicTypeBasedParameterResolver extends TypeBasedParameterResolver { @Override public String resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { Class parameterAnnotation = parameterContext.getParameter().getAnnotations()[0].annotationType(); return String.format("%s %s", extensionContext.getDisplayName(), parameterAnnotation.getSimpleName()); } } static class SubClassedBasicTypeBasedParameterResolver extends BasicTypeBasedParameterResolver { } static class ParameterizedTypeBasedParameterResolver extends TypeBasedParameterResolver>> { @Override public Map> resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return Map.of("ids", List.of(1, 42)); } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @interface TestAnnotation { } static class Sample { void methodWithBasicTypeParameter(@TestAnnotation String string) { } void methodWithObjectParameter(Object nothing) { } void methodWithParameterizedTypeParameter(Map> map) { } void methodWithAnotherParameterizedTypeParameter(Map> nothing) { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/subpackage/000077500000000000000000000000001455764576500302525ustar00rootroot00000000000000SubclassedAssertionsTests.java000066400000000000000000000017151455764576500362300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.subpackage; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; /** * Tests which verify that {@link Assertions} can be subclassed. * * @since 5.3 */ class SubclassedAssertionsTests extends Assertions { @Test void assertTrueWithBooleanTrue() { assertTrue(true); assertTrue(true, "test"); assertTrue(true, () -> "test"); } @Test void assertFalseWithBooleanTrue() { AssertionFailedError error = assertThrows(AssertionFailedError.class, () -> assertFalse(true)); assertEquals("expected: but was: ", error.getMessage()); } } SubclassedAssumptionsTests.java000066400000000000000000000021761455764576500364250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.subpackage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; /** * Tests which verify that {@link Assumptions} can be subclassed. * * @since 5.3 */ class SubclassedAssumptionsTests extends Assumptions { @Test void assumeTrueWithBooleanTrue() { String foo = null; try { assumeTrue(true); foo = "foo"; } finally { assertEquals("foo", foo); } } @Test void assumeFalseWithBooleanTrue() { TestAbortedException exception = assertThrows(TestAbortedException.class, () -> assumeFalse(true)); assertEquals("Assumption failed: assumption is not false", exception.getMessage()); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/000077500000000000000000000000001455764576500266415ustar00rootroot00000000000000AbstractJupiterTestEngineTests.java000066400000000000000000000045571455764576500355570ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.Set; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; /** * Abstract base class for tests involving the {@link JupiterTestEngine}. * * @since 5.0 */ public abstract class AbstractJupiterTestEngineTests { private final JupiterTestEngine engine = new JupiterTestEngine(); protected EngineExecutionResults executeTestsForClass(Class testClass) { return executeTests(selectClass(testClass)); } protected EngineExecutionResults executeTests(DiscoverySelector... selectors) { return executeTests(request().selectors(selectors).build()); } protected EngineExecutionResults executeTests(LauncherDiscoveryRequest request) { return EngineTestKit.execute(this.engine, request); } protected TestDescriptor discoverTests(DiscoverySelector... selectors) { return discoverTests(request().selectors(selectors).build()); } protected TestDescriptor discoverTests(LauncherDiscoveryRequest request) { return engine.discover(request, UniqueId.forEngine(engine.getId())); } protected UniqueId discoverUniqueId(Class clazz, String methodName) { TestDescriptor engineDescriptor = discoverTests(selectMethod(clazz, methodName)); Set descendants = engineDescriptor.getDescendants(); // @formatter:off TestDescriptor testDescriptor = descendants.stream() .skip(descendants.size() - 1) .findFirst() .orElseGet(() -> fail("no descendants")); // @formatter:on return testDescriptor.getUniqueId(); } } AtypicalJvmMethodNameTests.java000066400000000000000000000036721455764576500346450ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.engine.kotlin.ArbitraryNamingKotlinTestCase.METHOD_NAME; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.kotlin.ArbitraryNamingKotlinTestCase; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for JVM languages that allow special characters * in method names (e.g., Kotlin, Groovy, etc.) which are forbidden in * Java source code. * * @since 5.1 */ class AtypicalJvmMethodNameTests extends AbstractJupiterTestEngineTests { @Test void kotlinTestWithMethodNameContainingSpecialCharacters() { EngineExecutionResults executionResults = executeTestsForClass(ArbitraryNamingKotlinTestCase.class); assertThat(executionResults.testEvents().started().count()).isEqualTo(2); TestDescriptor testDescriptor1 = executionResults.testEvents().succeeded().list().get(0).getTestDescriptor(); assertAll(// () -> assertEquals(METHOD_NAME + "()", testDescriptor1.getDisplayName()), // () -> assertEquals(METHOD_NAME + "()", testDescriptor1.getLegacyReportingName())); TestDescriptor testDescriptor2 = executionResults.testEvents().succeeded().list().get(1).getTestDescriptor(); assertAll(// () -> assertEquals("test name ends with parentheses()()", testDescriptor2.getDisplayName()), // () -> assertEquals("test name ends with parentheses()()", testDescriptor2.getLegacyReportingName())); } } BeforeAllAndAfterAllComposedAnnotationTests.java000066400000000000000000000033241455764576500400700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** * Integration tests that verify support for {@link BeforeAll} and {@link AfterAll} * when used as meta-annotations in the {@link JupiterTestEngine}. * * @since 5.0 * @see BeforeEachAndAfterEachComposedAnnotationTests */ class BeforeAllAndAfterAllComposedAnnotationTests extends AbstractJupiterTestEngineTests { private static final List methodsInvoked = new ArrayList<>(); @Test void beforeAllAndAfterAllAsMetaAnnotations() { executeTestsForClass(TestCase.class).testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); assertThat(methodsInvoked).containsExactly("beforeAll", "test", "afterAll"); } static class TestCase { @CustomBeforeAll static void beforeAll() { methodsInvoked.add("beforeAll"); } @Test void test() { methodsInvoked.add("test"); } @CustomAfterAll static void afterAll() { methodsInvoked.add("afterAll"); } } @BeforeAll @Retention(RetentionPolicy.RUNTIME) private @interface CustomBeforeAll { } @AfterAll @Retention(RetentionPolicy.RUNTIME) private @interface CustomAfterAll { } } BeforeEachAndAfterEachComposedAnnotationTests.java000066400000000000000000000033301455764576500403450ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Integration tests that verify support for {@link BeforeEach} and {@link AfterEach} * when used as meta-annotations in the {@link JupiterTestEngine}. * * @since 5.0 * @see BeforeAllAndAfterAllComposedAnnotationTests */ class BeforeEachAndAfterEachComposedAnnotationTests extends AbstractJupiterTestEngineTests { private static final List methodsInvoked = new ArrayList<>(); @Test void beforeEachAndAfterEachAsMetaAnnotations() { executeTestsForClass(TestCase.class).testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); assertThat(methodsInvoked).containsExactly("beforeEach", "test", "afterEach"); } static class TestCase { @CustomBeforeEach void beforeEach() { methodsInvoked.add("beforeEach"); } @Test void test() { methodsInvoked.add("test"); } @CustomAfterEach void afterEach() { methodsInvoked.add("afterEach"); } } @BeforeEach @Retention(RetentionPolicy.RUNTIME) private @interface CustomBeforeEach { } @AfterEach @Retention(RetentionPolicy.RUNTIME) private @interface CustomAfterEach { } } DefaultExecutionModeTests.java000066400000000000000000000167041455764576500345350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.CONCURRENT; import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.SAME_THREAD; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.hierarchical.Node; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; class DefaultExecutionModeTests extends AbstractJupiterTestEngineTests { @Test void defaultExecutionModeIsReadFromConfigurationParameter() { assertUsesExpectedExecutionMode(null, SAME_THREAD); assertUsesExpectedExecutionMode(SAME_THREAD, SAME_THREAD); assertUsesExpectedExecutionMode(CONCURRENT, CONCURRENT); } private void assertUsesExpectedExecutionMode(ExecutionMode defaultExecutionMode, ExecutionMode expectedExecutionMode) { var engineDescriptor = discoverTestsWithDefaultExecutionMode(TestCase.class, defaultExecutionMode); assertExecutionModeRecursively(engineDescriptor, expectedExecutionMode); } @Test void annotationOverridesDefaultExecutionModeToConcurrentForAllDescendants() { assertUsesExpectedExecutionModeForTestClassAndItsDescendants(ConcurrentTestCase.class, null, CONCURRENT); assertUsesExpectedExecutionModeForTestClassAndItsDescendants(ConcurrentTestCase.class, SAME_THREAD, CONCURRENT); assertUsesExpectedExecutionModeForTestClassAndItsDescendants(ConcurrentTestCase.class, CONCURRENT, CONCURRENT); } @Test void annotationOverridesDefaultExecutionModeToSameThreadForAllDescendants() { assertUsesExpectedExecutionModeForTestClassAndItsDescendants(SameThreadTestCase.class, null, SAME_THREAD); assertUsesExpectedExecutionModeForTestClassAndItsDescendants(SameThreadTestCase.class, SAME_THREAD, SAME_THREAD); assertUsesExpectedExecutionModeForTestClassAndItsDescendants(SameThreadTestCase.class, CONCURRENT, SAME_THREAD); } private void assertUsesExpectedExecutionModeForTestClassAndItsDescendants(Class testClass, ExecutionMode defaultExecutionMode, ExecutionMode expectedExecutionMode) { var engineDescriptor = discoverTestsWithDefaultExecutionMode(testClass, defaultExecutionMode); engineDescriptor.getChildren().forEach(child -> assertExecutionModeRecursively(child, expectedExecutionMode)); } private void assertExecutionModeRecursively(TestDescriptor testDescriptor, ExecutionMode expectedExecutionMode) { assertExecutionMode(testDescriptor, expectedExecutionMode); testDescriptor.getChildren().forEach(child -> assertExecutionModeRecursively(child, expectedExecutionMode)); } @Test void methodsInTestClassesWithInstancePerClassHaveExecutionModeSameThread() { var engineDescriptor = discoverTestsWithDefaultExecutionMode(SimpleTestInstancePerClassTestCase.class, CONCURRENT); var classDescriptor = getOnlyElement(engineDescriptor.getChildren()); classDescriptor.getChildren().forEach(child -> assertExecutionModeRecursively(child, SAME_THREAD)); } @Test void methodsInNestedTestClassesWithInstancePerClassInHierarchyHaveExecutionModeSameThread() { var engineDescriptor = discoverTestsWithDefaultExecutionMode(OuterTestCase.class, CONCURRENT); var outerTestCaseClassDescriptor = firstChild(engineDescriptor, ClassTestDescriptor.class); var outerTestMethodDescriptor = firstChild(outerTestCaseClassDescriptor, TestMethodTestDescriptor.class); var level1NestedClassDescriptor = firstChild(outerTestCaseClassDescriptor, NestedClassTestDescriptor.class); var level1TestMethodDescriptor = firstChild(level1NestedClassDescriptor, TestMethodTestDescriptor.class); var level2NestedClassDescriptor = firstChild(level1NestedClassDescriptor, NestedClassTestDescriptor.class); var level2TestMethodDescriptor = firstChild(level2NestedClassDescriptor, TestMethodTestDescriptor.class); var level3NestedClassDescriptor = firstChild(level2NestedClassDescriptor, NestedClassTestDescriptor.class); var level3TestMethodDescriptor = firstChild(level3NestedClassDescriptor, TestMethodTestDescriptor.class); assertExecutionMode(outerTestCaseClassDescriptor, CONCURRENT); assertExecutionMode(outerTestMethodDescriptor, CONCURRENT); assertExecutionMode(level1NestedClassDescriptor, CONCURRENT); assertExecutionMode(level1TestMethodDescriptor, CONCURRENT); assertExecutionMode(level2NestedClassDescriptor, CONCURRENT); assertExecutionMode(level2TestMethodDescriptor, SAME_THREAD); assertExecutionMode(level3NestedClassDescriptor, SAME_THREAD); assertExecutionMode(level3TestMethodDescriptor, SAME_THREAD); } private JupiterEngineDescriptor discoverTestsWithDefaultExecutionMode(Class testClass, ExecutionMode executionMode) { LauncherDiscoveryRequestBuilder request = request().selectors(selectClass(testClass)); if (executionMode != null) { request.configurationParameter(Constants.DEFAULT_PARALLEL_EXECUTION_MODE, executionMode.name()); } return (JupiterEngineDescriptor) discoverTests(request.build()); } private static void assertExecutionMode(TestDescriptor testDescriptor, ExecutionMode expectedExecutionMode) { assertThat(((Node) testDescriptor).getExecutionMode()) // .describedAs("ExecutionMode for %s", testDescriptor) // .isEqualTo(expectedExecutionMode); } @SuppressWarnings("unchecked") private T firstChild(TestDescriptor engineDescriptor, Class testDescriptorClass) { return (T) engineDescriptor.getChildren().stream() // .filter(testDescriptorClass::isInstance) // .findFirst() // .orElseGet(() -> fail("No child of type " + testDescriptorClass + " found")); } static class TestCase { @Test void test() { } @Nested class NestedTestCase { @Test void test() { } } } @TestInstance(PER_CLASS) static class SimpleTestInstancePerClassTestCase extends TestCase { } @Execution(org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT) static class ConcurrentTestCase extends TestCase { } @Execution(org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD) static class SameThreadTestCase extends TestCase { } static class OuterTestCase { @Nested class LevelOne { @Nested @TestInstance(PER_CLASS) class LevelTwo { @Nested class LevelThree { @Test void test() { } } @Test void test() { } } @Test void test() { } } @Test void test() { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/DefaultMethodTests.java000066400000000000000000000216631455764576500332640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.engine.execution.injection.sample.DoubleParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.LongParameterResolver; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for selecting and executing default * methods from interfaces in conjunction with the {@link JupiterTestEngine}. * * @since 5.0 */ class DefaultMethodTests extends AbstractJupiterTestEngineTests { private static boolean beforeAllInvoked; private static boolean afterAllInvoked; private static boolean defaultMethodInvoked; private static boolean overriddenDefaultMethodInvoked; private static boolean localMethodInvoked; @BeforeEach void resetFlags() { beforeAllInvoked = false; afterAllInvoked = false; defaultMethodInvoked = false; overriddenDefaultMethodInvoked = false; localMethodInvoked = false; } @Test void executeTestCaseWithDefaultMethodFromInterfaceSelectedByFullyQualifedMethodName() { String fqmn = TestCaseWithDefaultMethod.class.getName() + "#test"; LauncherDiscoveryRequest request = request().selectors(selectMethod(fqmn)).build(); EngineExecutionResults executionResults = executeTests(request); // @formatter:off assertAll( () -> assertTrue(beforeAllInvoked, "@BeforeAll static method invoked from interface"), () -> assertTrue(afterAllInvoked, "@AfterAll static method invoked from interface"), () -> assertTrue(defaultMethodInvoked, "default @Test method invoked from interface"), () -> assertEquals(1, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on } @Test void executeTestCaseWithDefaultMethodFromGenericInterfaceSelectedByFullyQualifedMethodName() { String fqmn = GenericTestCaseWithDefaultMethod.class.getName() + "#test(" + Long.class.getName() + ")"; LauncherDiscoveryRequest request = request().selectors(selectMethod(fqmn)).build(); EngineExecutionResults executionResults = executeTests(request); // @formatter:off assertAll( () -> assertTrue(beforeAllInvoked, "@BeforeAll default method invoked from interface"), () -> assertTrue(afterAllInvoked, "@AfterAll default method invoked from interface"), () -> assertTrue(defaultMethodInvoked, "default @Test method invoked from interface"), () -> assertFalse(localMethodInvoked, "local @Test method should not have been invoked from class"), () -> assertEquals(1, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on } @Test void executeTestCaseWithOverloadedMethodNextToGenericDefaultMethodSelectedByFullyQualifedMethodName() { String fqmn = GenericTestCaseWithDefaultMethod.class.getName() + "#test(" + Double.class.getName() + ")"; LauncherDiscoveryRequest request = request().selectors(selectMethod(fqmn)).build(); EngineExecutionResults executionResults = executeTests(request); // @formatter:off assertAll( () -> assertTrue(beforeAllInvoked, "@BeforeAll default method invoked from interface"), () -> assertTrue(afterAllInvoked, "@AfterAll default method invoked from interface"), () -> assertFalse(defaultMethodInvoked, "default @Test method should not have been invoked from interface"), () -> assertTrue(localMethodInvoked, "local @Test method invoked from class"), () -> assertEquals(1, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on } @Test void executeTestCaseWithOverloadedMethodNextToGenericDefaultMethodSelectedByClass() { Class clazz = GenericTestCaseWithDefaultMethod.class; LauncherDiscoveryRequest request = request().selectors(selectClass(clazz)).build(); EngineExecutionResults executionResults = executeTests(request); // @formatter:off assertAll( () -> assertTrue(beforeAllInvoked, "@BeforeAll default method invoked from interface"), () -> assertTrue(afterAllInvoked, "@AfterAll default method invoked from interface"), () -> assertTrue(defaultMethodInvoked, "default @Test method invoked from interface"), () -> assertTrue(localMethodInvoked, "local @Test method invoked from class"), () -> assertEquals(2, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on } @Test void executeTestCaseWithOverriddenGenericDefaultMethodSelectedByClass() { Class clazz = GenericTestCaseWithOverriddenDefaultMethod.class; LauncherDiscoveryRequest request = request().selectors(selectClass(clazz)).build(); EngineExecutionResults executionResults = executeTests(request); // @formatter:off assertAll( () -> assertTrue(beforeAllInvoked, "@BeforeAll default method invoked from interface"), () -> assertTrue(afterAllInvoked, "@AfterAll default method invoked from interface"), () -> assertFalse(defaultMethodInvoked, "default @Test method should not have been invoked from interface"), () -> assertTrue(overriddenDefaultMethodInvoked, "overridden default @Test method invoked from interface"), () -> assertTrue(localMethodInvoked, "local @Test method invoked from class"), // If defaultMethodInvoked is false and the following ends up being // 3 instead of 2, that means that the overriding method gets invoked // twice: once as itself and a second time "as" the default method which // should not have been "discovered" since it is overridden. () -> assertEquals(2, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on } // ------------------------------------------------------------------------- interface TestInterface { @BeforeAll static void beforeAll() { beforeAllInvoked = true; } @Test default void test() { defaultMethodInvoked = true; } @AfterAll static void afterAll() { afterAllInvoked = true; } } static class TestCaseWithDefaultMethod implements TestInterface { } @ExtendWith({ LongParameterResolver.class, DoubleParameterResolver.class }) @TestInstance(Lifecycle.PER_CLASS) interface GenericTestInterface { @BeforeAll default void beforeAll() { beforeAllInvoked = true; } @Test default void test(N number) { defaultMethodInvoked = true; assertThat(number.intValue()).isEqualTo(42); } @AfterAll default void afterAll() { afterAllInvoked = true; } } static class GenericTestCaseWithDefaultMethod implements GenericTestInterface { @Test void test(Double number) { localMethodInvoked = true; assertThat(number).isEqualTo(42.0); } } static class GenericTestCaseWithOverriddenDefaultMethod implements GenericTestInterface { @Test @Override public void test(Long number) { overriddenDefaultMethodInvoked = true; assertThat(number.intValue()).isEqualTo(42); } @Test void test(Double number) { localMethodInvoked = true; assertThat(number).isEqualTo(42.0); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/DisabledTests.java000066400000000000000000000041541455764576500322420ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.test; import java.lang.reflect.Method; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for {@link Disabled @Disabled} in the * {@link JupiterTestEngine}. * * @since 5.0 */ class DisabledTests extends AbstractJupiterTestEngineTests { @Test void executeTestsWithDisabledTestClass() { EngineExecutionResults results = executeTestsForClass(DisabledTestClassTestCase.class); results.containerEvents().assertStatistics(stats -> stats.skipped(1)); results.testEvents().assertStatistics(stats -> stats.started(0)); } @Test void executeTestsWithDisabledTestMethods() throws Exception { String methodName = "disabledTest"; Method method = DisabledTestMethodsTestCase.class.getDeclaredMethod(methodName); executeTestsForClass(DisabledTestMethodsTestCase.class).testEvents()// .assertStatistics(stats -> stats.skipped(1).started(1).finished(1).aborted(0).succeeded(1).failed(0))// .skipped().assertEventsMatchExactly( event(test(methodName), skippedWithReason(method + " is @Disabled"))); } // ------------------------------------------------------------------- @Disabled static class DisabledTestClassTestCase { @Test void disabledTest() { fail("this should be @Disabled"); } } static class DisabledTestMethodsTestCase { @Test void enabledTest() { } @Test @Disabled void disabledTest() { fail("this should be @Disabled"); } } } DynamicNodeGenerationTests.java000066400000000000000000000605101455764576500346600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Fail.fail; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor.DYNAMIC_CONTAINER_SEGMENT_TYPE; import static org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor.DYNAMIC_TEST_SEGMENT_TYPE; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.dynamicTestRegistered; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Event; import org.junit.platform.testkit.engine.Events; /** * Integration tests for {@link TestFactory @TestFactory}, {@link DynamicTest}, * and {@link org.junit.jupiter.api.DynamicContainer}. * * @since 5.0 */ class DynamicNodeGenerationTests extends AbstractJupiterTestEngineTests { @Test void testFactoryMethodsAreCorrectlyDiscoveredForClassSelector() { LauncherDiscoveryRequest request = request().selectors(selectClass(MyDynamicTestCase.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertThat(engineDescriptor.getDescendants()).as("# resolved test descriptors").hasSize(13); } @Test void testFactoryMethodIsCorrectlyDiscoveredForMethodSelector() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyDynamicTestCase.class, "dynamicStream")).build(); TestDescriptor engineDescriptor = discoverTests(request); assertThat(engineDescriptor.getDescendants()).as("# resolved test descriptors").hasSize(2); } @Test void dynamicTestsAreExecutedFromStream() { EngineExecutionResults executionResults = executeTests(selectMethod(MyDynamicTestCase.class, "dynamicStream")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicStream"), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamicStream"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void dynamicTestsAreExecutedFromCollection() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicCollection")); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertAll( // () -> assertEquals(3, containers.started().count(), "# container started"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(3, containers.finished().count(), "# container finished")); } @Test void dynamicTestsAreExecutedFromIterator() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicIterator")); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertAll( // () -> assertEquals(3, containers.started().count(), "# container started"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(3, containers.finished().count(), "# container finished")); } @Test void dynamicTestsAreExecutedFromIterable() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicIterable")); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); // @TestFactory methods are counted as both container and test assertAll( // () -> assertEquals(3, containers.started().count(), "# container started"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(3, containers.finished().count(), "# container finished")); } @Test void singleDynamicTestIsExecutedWhenDiscoveredByUniqueId() { UniqueId uniqueId = discoverUniqueId(MyDynamicTestCase.class, "dynamicStream") // .append(DYNAMIC_TEST_SEGMENT_TYPE, "#2"); EngineExecutionResults executionResults = executeTests(selectUniqueId(uniqueId)); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicStream"), started()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamicStream"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void singleDynamicTestIsExecutedWhenDiscoveredByIterationIndex() { var methodSelector = selectMethod(MyDynamicTestCase.class, "dynamicStream"); EngineExecutionResults executionResults = executeTests(selectIteration(methodSelector, 1)); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicStream"), started()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamicStream"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void multipleDynamicTestsAreExecutedWhenDiscoveredByIterationIndexAndUniqueId() { UniqueId uniqueId = discoverUniqueId(MyDynamicTestCase.class, "threeTests") // .append(DYNAMIC_TEST_SEGMENT_TYPE, "#3"); var methodSelector = selectMethod(MyDynamicTestCase.class, "threeTests"); EngineExecutionResults executionResults = executeTests(selectIteration(methodSelector, 1), selectUniqueId(uniqueId)); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("threeTests"), started()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "two"), started()), // event(test("dynamic-test:#2", "two"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#3")), // event(test("dynamic-test:#3", "three"), started()), // event(test("dynamic-test:#3", "three"), finishedSuccessfully()), // event(container("threeTests"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void dynamicContainersAreExecutedFromIterable() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicContainerWithIterable")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicContainerWithIterable"), started()), // event(dynamicTestRegistered("dynamic-container:#1")), // event(container("dynamic-container:#1"), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamic-container:#1"), finishedSuccessfully()), // event(container("dynamicContainerWithIterable"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertAll( // () -> assertEquals(4, containers.started().count(), "# container started"), () -> assertEquals(1, containers.dynamicallyRegistered().count(), "# dynamic containers registered"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic tests registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(4, containers.finished().count(), "# container finished")); } @Test void singleDynamicTestInNestedDynamicContainerIsExecutedWhenDiscoveredByUniqueId() { UniqueId uniqueId = discoverUniqueId(MyDynamicTestCase.class, "twoNestedContainersWithTwoTestsEach") // .append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#1") // .append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#1") // .append(DYNAMIC_TEST_SEGMENT_TYPE, "#2"); EngineExecutionResults executionResults = executeTests(selectUniqueId(uniqueId)); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("twoNestedContainersWithTwoTestsEach"), started()), // event(dynamicTestRegistered(displayName("a"))), // event(container(displayName("a")), started()), // event(dynamicTestRegistered(displayName("a1"))), // event(container(displayName("a1")), started()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container(displayName("a1")), finishedSuccessfully()), // event(container(displayName("a")), finishedSuccessfully()), // event(container("twoNestedContainersWithTwoTestsEach"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void allDynamicTestInNestedDynamicContainerAreExecutedWhenContainerIsDiscoveredByUniqueId() { UniqueId uniqueId = discoverUniqueId(MyDynamicTestCase.class, "twoNestedContainersWithTwoTestsEach") // .append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#2") // .append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#1"); EngineExecutionResults executionResults = executeTests(selectUniqueId(uniqueId)); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("twoNestedContainersWithTwoTestsEach"), started()), // event(dynamicTestRegistered(displayName("b"))), // event(container(displayName("b")), started()), // event(dynamicTestRegistered(displayName("b1"))), // event(container(displayName("b1")), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container(displayName("b1")), finishedSuccessfully()), // event(container(displayName("b")), finishedSuccessfully()), // event(container("twoNestedContainersWithTwoTestsEach"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void nestedDynamicContainersAreExecuted() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "nestedDynamicContainers")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("nestedDynamicContainers"), started()), // event(dynamicTestRegistered(displayName("gift wrap"))), // event(container(displayName("gift wrap")), started()), // event(dynamicTestRegistered(displayName("box"))), // event(container(displayName("box")), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container(displayName("box")), finishedSuccessfully()), // event(container(displayName("gift wrap")), finishedSuccessfully()), // event(container("nestedDynamicContainers"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertAll( // () -> assertEquals(5, containers.started().count(), "# container started"), () -> assertEquals(2, containers.dynamicallyRegistered().count(), "# dynamic containers registered"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic tests registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(5, containers.finished().count(), "# container finished")); } @Test void legacyReportingNames() { Events dynamicRegistrations = executeTests(selectMethod(MyDynamicTestCase.class, "nestedDynamicContainers"))// .allEvents().dynamicallyRegistered(); // @formatter:off Stream legacyReportingNames = dynamicRegistrations .map(Event::getTestDescriptor) .map(TestDescriptor::getLegacyReportingName); assertThat(legacyReportingNames) .containsExactly("nestedDynamicContainers()[1]", "nestedDynamicContainers()[1][1]", "nestedDynamicContainers()[1][1][1]", "nestedDynamicContainers()[1][1][2]"); // @formatter:on } @Test void dynamicContainersAreExecutedFromExceptionThrowingStream() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicContainerWithExceptionThrowingStream")); assertTrue(MyDynamicTestCase.exceptionThrowingStreamClosed.get(), "stream should be closed"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicContainerWithExceptionThrowingStream"), started()), // event(dynamicTestRegistered("dynamic-container:#1")), // event(container("dynamic-container:#1"), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamic-container:#1"), finishedWithFailure(instanceOf(ArrayIndexOutOfBoundsException.class))), // event(container("dynamicContainerWithExceptionThrowingStream"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertAll( // () -> assertEquals(4, containers.started().count(), "# container started"), () -> assertEquals(1, containers.dynamicallyRegistered().count(), "# dynamic containers registered"), () -> assertEquals(2, tests.dynamicallyRegistered().count(), "# dynamic tests registered"), () -> assertEquals(2, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(1, tests.failed().count(), "# tests failed"), () -> assertEquals(4, containers.finished().count(), "# container finished")); } @Test void dynamicContainersChildrenMustNotBeNull() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "dynamicContainerWithNullChildren")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("dynamicContainerWithNullChildren"), started()), // event(dynamicTestRegistered("dynamic-container:#1")), // event(container("dynamic-container:#1"), started()), // event(container("dynamic-container:#1"), // finishedWithFailure(message("individual dynamic node must not be null"))), // event(container("dynamicContainerWithNullChildren"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void testFactoryMethodsMayReturnSingleDynamicContainer() { EngineExecutionResults executionResults = executeTests( selectMethod(MyDynamicTestCase.class, "singleContainer")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("singleContainer"), started()), // event(dynamicTestRegistered("dynamic-container:#1")), // event(container("dynamic-container:#1"), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamic-test:#2")), // event(test("dynamic-test:#2", "failingTest"), started()), // event(test("dynamic-test:#2", "failingTest"), finishedWithFailure(message("failing"))), // event(container("dynamic-container:#1"), finishedSuccessfully()), // event(container("singleContainer"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void testFactoryMethodsMayReturnSingleDynamicTest() { EngineExecutionResults executionResults = executeTests(selectMethod(MyDynamicTestCase.class, "singleTest")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MyDynamicTestCase.class), started()), // event(container("singleTest"), started()), // event(dynamicTestRegistered("dynamic-test:#1")), // event(test("dynamic-test:#1", "succeedingTest"), started()), // event(test("dynamic-test:#1", "succeedingTest"), finishedSuccessfully()), // event(container("singleTest"), finishedSuccessfully()), // event(container(MyDynamicTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } static class MyDynamicTestCase { private static final List list = Arrays.asList( dynamicTest("succeedingTest", () -> assertTrue(true, "succeeding")), dynamicTest("failingTest", () -> fail("failing"))); private static final AtomicBoolean exceptionThrowingStreamClosed = new AtomicBoolean(false); @TestFactory Collection dynamicCollection() { return list; } @TestFactory Stream dynamicStream() { return list.stream(); } @TestFactory Iterator dynamicIterator() { return list.iterator(); } @TestFactory Iterable dynamicIterable() { return this::dynamicIterator; } @TestFactory Iterable dynamicContainerWithIterable() { return singleton(dynamicContainer("box", list)); } @TestFactory Iterable nestedDynamicContainers() { return singleton(dynamicContainer("gift wrap", singleton(dynamicContainer("box", list)))); } @TestFactory Stream twoNestedContainersWithTwoTestsEach() { return Stream.of( // dynamicContainer("a", singleton(dynamicContainer("a1", list))), // dynamicContainer("b", singleton(dynamicContainer("b1", list))) // ); } @TestFactory Iterable dynamicContainerWithExceptionThrowingStream() { // @formatter:off return singleton(dynamicContainer("box", IntStream.rangeClosed(0, 100) .mapToObj(list::get) .onClose(() -> exceptionThrowingStreamClosed.set(true)))); // @formatter:on } @TestFactory Iterable dynamicContainerWithNullChildren() { return singleton(dynamicContainer("box", singleton(null))); } @TestFactory DynamicNode singleContainer() { return dynamicContainer("box", list); } @TestFactory DynamicNode singleTest() { return dynamicTest("succeedingTest", () -> assertTrue(true)); } @TestFactory Stream threeTests() { return Stream.of( // dynamicTest("one", () -> assertTrue(true)), // dynamicTest("two", () -> assertTrue(true)), // dynamicTest("three", () -> assertTrue(true)) // ); } } } ExceptionHandlingTests.java000066400000000000000000000321031455764576500340520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.suppressed; import java.io.IOException; import java.util.Optional; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; import org.opentest4j.AssertionFailedError; import org.opentest4j.TestAbortedException; /** * Integration tests that verify correct exception handling in the {@link JupiterTestEngine}. * * @since 5.0 */ class ExceptionHandlingTests extends AbstractJupiterTestEngineTests { @Test void failureInTestMethodIsRegistered() { EngineExecutionResults executionResults = executeTests(selectMethod(FailureTestCase.class, "failingTest")); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1)); tests.failed().assertEventsMatchExactly( // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionFailedError.class), message("always fails")))); } @Test void uncheckedExceptionInTestMethodIsRegistered() { EngineExecutionResults executionResults = executeTests( selectMethod(FailureTestCase.class, "testWithUncheckedException")); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1)); tests.failed().assertEventsMatchExactly( // event(test("testWithUncheckedException"), finishedWithFailure(instanceOf(RuntimeException.class), message("unchecked")))); } @Test void checkedExceptionInTestMethodIsRegistered() { EngineExecutionResults executionResults = executeTests( selectMethod(FailureTestCase.class, "testWithCheckedException")); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1)); tests.failed().assertEventsMatchExactly( // event(test("testWithCheckedException"), finishedWithFailure(instanceOf(IOException.class), message("checked")))); } @Test void checkedExceptionInBeforeEachIsRegistered() { FailureTestCase.exceptionToThrowInBeforeEach = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(FailureTestCase.class, "succeedingTest")); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1)); tests.failed().assertEventsMatchExactly( event(test("succeedingTest"), finishedWithFailure(instanceOf(IOException.class), message("checked")))); } @Test void checkedExceptionInAfterEachIsRegistered() { FailureTestCase.exceptionToThrowInAfterEach = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(FailureTestCase.class, "succeedingTest")); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1)); tests.failed().assertEventsMatchExactly( event(test("succeedingTest"), finishedWithFailure(instanceOf(IOException.class), message("checked")))); } @Test void checkedExceptionInAfterEachIsSuppressedByExceptionInTest() { Class testClass = FailureTestCase.class; FailureTestCase.exceptionToThrowInAfterEach = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(testClass, "testWithUncheckedException")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("testWithUncheckedException"), started()), // event(test("testWithUncheckedException"), // finishedWithFailure( // instanceOf(RuntimeException.class), // message("unchecked"), // suppressed(0, instanceOf(IOException.class), message("checked")))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void exceptionInAfterEachTakesPrecedenceOverFailedAssumptionInTest() { FailureTestCase.exceptionToThrowInAfterEach = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(FailureTestCase.class, "abortedTest")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(FailureTestCase.class), started()), // event(test("abortedTest"), started()), // event(test("abortedTest"), // finishedWithFailure(instanceOf(IOException.class), message("checked"), // suppressed(0, instanceOf(TestAbortedException.class)))), // event(container(FailureTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void checkedExceptionInBeforeAllIsRegistered() { Class testClass = FailureTestCase.class; FailureTestCase.exceptionToThrowInBeforeAll = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(testClass, "succeedingTest")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(IOException.class), message("checked"))), // event(engine(), finishedSuccessfully())); } @Test void checkedExceptionInAfterAllIsRegistered() { Class testClass = FailureTestCase.class; FailureTestCase.exceptionToThrowInAfterAll = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(testClass, "succeedingTest")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("succeedingTest"), started()), // event(test("succeedingTest"), finishedSuccessfully()), // event(container(testClass), finishedWithFailure(instanceOf(IOException.class), message("checked"))), // event(engine(), finishedSuccessfully())); } @Test void exceptionInAfterAllCallbackDoesNotHideExceptionInBeforeAllCallback() { Class testClass = TestCaseWithThrowingBeforeAllAndAfterAllCallbacks.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure( // message("beforeAll callback"), // suppressed(0, message("afterAll callback")))), // event(engine(), finishedSuccessfully())); } @Test void exceptionsInConstructorAndAfterAllCallbackAreReportedWhenTestInstancePerMethodIsUsed() { Class testClass = TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerMethodLifecycle.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("test"), started()), // event(test("test"), finishedWithFailure(message("constructor"))), // event(container(testClass), finishedWithFailure(message("afterAll callback"))), // event(engine(), finishedSuccessfully())); } @Test void exceptionInConstructorPreventsExecutionOfAfterAllCallbacksWhenTestInstancePerClassIsUsed() { Class testClass = TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerClassLifecycle.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(message("constructor"))), event(engine(), finishedSuccessfully())); } @Test void failureInAfterAllTakesPrecedenceOverTestAbortedExceptionInBeforeAll() { FailureTestCase.exceptionToThrowInBeforeAll = Optional.of(new TestAbortedException("aborted")); FailureTestCase.exceptionToThrowInAfterAll = Optional.of(new IOException("checked")); EngineExecutionResults executionResults = executeTests(selectMethod(FailureTestCase.class, "succeedingTest")); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(FailureTestCase.class), started()), // event(container(FailureTestCase.class), finishedWithFailure(instanceOf(IOException.class), message("checked"), suppressed(0, instanceOf(TestAbortedException.class), message("aborted")))), // event(engine(), finishedSuccessfully())); } @AfterEach void cleanUpExceptions() { FailureTestCase.exceptionToThrowInBeforeAll = Optional.empty(); FailureTestCase.exceptionToThrowInAfterAll = Optional.empty(); FailureTestCase.exceptionToThrowInBeforeEach = Optional.empty(); FailureTestCase.exceptionToThrowInAfterEach = Optional.empty(); } // ------------------------------------------------------------------------- static class FailureTestCase { static Optional exceptionToThrowInBeforeAll = Optional.empty(); static Optional exceptionToThrowInAfterAll = Optional.empty(); static Optional exceptionToThrowInBeforeEach = Optional.empty(); static Optional exceptionToThrowInAfterEach = Optional.empty(); @BeforeAll static void beforeAll() throws Throwable { if (exceptionToThrowInBeforeAll.isPresent()) { throw exceptionToThrowInBeforeAll.get(); } } @AfterAll static void afterAll() throws Throwable { if (exceptionToThrowInAfterAll.isPresent()) { throw exceptionToThrowInAfterAll.get(); } } @BeforeEach void beforeEach() throws Throwable { if (exceptionToThrowInBeforeEach.isPresent()) { throw exceptionToThrowInBeforeEach.get(); } } @AfterEach void afterEach() throws Throwable { if (exceptionToThrowInAfterEach.isPresent()) { throw exceptionToThrowInAfterEach.get(); } } @Test void succeedingTest() { } @Test void failingTest() { Assertions.fail("always fails"); } @Test void testWithUncheckedException() { throw new RuntimeException("unchecked"); } @Test void testWithCheckedException() throws IOException { throw new IOException("checked"); } @Test void abortedTest() { assumeFalse(true, "abortedTest"); } } @TestInstance(PER_METHOD) @ExtendWith(ThrowingAfterAllCallback.class) static class TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerMethodLifecycle { TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerMethodLifecycle() { throw new IllegalStateException("constructor"); } @Test void test() { } } @TestInstance(PER_CLASS) @ExtendWith(ThrowingAfterAllCallback.class) static class TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerClassLifecycle { TestCaseWithInvalidConstructorAndThrowingAfterAllCallbackAndPerClassLifecycle() { throw new IllegalStateException("constructor"); } @Test void test() { } } @ExtendWith(ThrowingBeforeAllCallback.class) @ExtendWith(ThrowingAfterAllCallback.class) static class TestCaseWithThrowingBeforeAllAndAfterAllCallbacks { @Test void test() { } } static class ThrowingBeforeAllCallback implements BeforeAllCallback { @Override public void beforeAll(ExtensionContext context) { throw new IllegalStateException("beforeAll callback"); } } static class ThrowingAfterAllCallback implements AfterAllCallback { @Override public void afterAll(ExtensionContext context) { throw new IllegalStateException("afterAll callback"); } } } FailedAssumptionsTests.java000066400000000000000000000033661455764576500341120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import org.junit.Assume; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for failed assumptions in the * {@link JupiterTestEngine}. * * @since 5.4 */ class FailedAssumptionsTests extends AbstractJupiterTestEngineTests { @Test void testAbortedExceptionInBeforeAll() { EngineExecutionResults results = executeTestsForClass(TestAbortedExceptionInBeforeAllTestCase.class); results.containerEvents().assertStatistics(stats -> stats.aborted(1)); results.testEvents().assertStatistics(stats -> stats.started(0)); } @Test void assumptionViolatedExceptionInBeforeAll() { EngineExecutionResults results = executeTestsForClass(AssumptionViolatedExceptionInBeforeAllTestCase.class); results.containerEvents().assertStatistics(stats -> stats.aborted(1)); results.testEvents().assertStatistics(stats -> stats.started(0)); } // ------------------------------------------------------------------- static class TestAbortedExceptionInBeforeAllTestCase { @BeforeAll static void beforeAll() { Assumptions.assumeTrue(false); } @Test void test() { } } static class AssumptionViolatedExceptionInBeforeAllTestCase { @BeforeAll static void beforeAll() { Assume.assumeTrue(false); } @Test void test() { } } } InvalidLifecycleMethodConfigurationTests.java000066400000000000000000000067061455764576500375600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests that verify proper handling of invalid configuration for * lifecycle methods in conjunction with the {@link JupiterTestEngine}. * *

In general, configuration errors should not be thrown until the * execution phase, thereby giving all containers a chance to execute. * * @since 5.0 */ class InvalidLifecycleMethodConfigurationTests extends AbstractJupiterTestEngineTests { @Test void executeValidTestCaseAlongsideTestCaseWithInvalidNonStaticBeforeAllDeclaration() { assertContainerFailed(TestCaseWithInvalidNonStaticBeforeAllMethod.class); } @Test void executeValidTestCaseAlongsideTestCaseWithInvalidNonStaticAfterAllDeclaration() { assertContainerFailed(TestCaseWithInvalidNonStaticAfterAllMethod.class); } @Test void executeValidTestCaseAlongsideTestCaseWithInvalidStaticBeforeEachDeclaration() { assertContainerFailed(TestCaseWithInvalidStaticBeforeEachMethod.class); } @Test void executeValidTestCaseAlongsideTestCaseWithInvalidStaticAfterEachDeclaration() { assertContainerFailed(TestCaseWithInvalidStaticAfterEachMethod.class); } private void assertContainerFailed(Class invalidTestClass) { EngineExecutionResults executionResults = executeTests(selectClass(TestCase.class), selectClass(invalidTestClass)); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); // @formatter:off assertAll( () -> assertEquals(3, containers.started().count(), "# containers started"), () -> assertEquals(1, tests.started().count(), "# tests started"), () -> assertEquals(1, tests.succeeded().count(), "# tests succeeded"), () -> assertEquals(0, tests.failed().count(), "# tests failed"), () -> assertEquals(3, containers.finished().count(), "# containers finished"), () -> assertEquals(1, containers.failed().count(), "# containers failed") ); // @formatter:on } // ------------------------------------------------------------------------- static class TestCase { @Test void test() { } } static class TestCaseWithInvalidNonStaticBeforeAllMethod { // must be static @BeforeAll void beforeAll() { } @Test void test() { } } static class TestCaseWithInvalidNonStaticAfterAllMethod { // must be static @AfterAll void afterAll() { } @Test void test() { } } static class TestCaseWithInvalidStaticBeforeEachMethod { // must NOT be static @BeforeEach static void beforeEach() { } @Test void test() { } } static class TestCaseWithInvalidStaticAfterEachMethod { // must NOT be static @AfterEach static void afterEach() { } @Test void test() { } } } JupiterTestEngineBasicTests.java000066400000000000000000000023351455764576500350250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * Basic assertions regarding {@link org.junit.platform.engine.TestEngine} * functionality in JUnit Jupiter. * * @since 5.0 */ class JupiterTestEngineBasicTests { private final JupiterTestEngine jupiter = new JupiterTestEngine(); @Test void id() { assertEquals("junit-jupiter", jupiter.getId()); } @Test void groupId() { assertEquals("org.junit.jupiter", jupiter.getGroupId().orElseThrow()); } @Test void artifactId() { assertEquals("junit-jupiter-engine", jupiter.getArtifactId().orElseThrow()); } @Test void version() { assertThat(jupiter.getVersion().orElseThrow()).isIn( // System.getProperty("developmentVersion"), // with Test Distribution "DEVELOPMENT" // without Test Distribution ); } } LifecycleMethodOverridingAndSupersedingTests.java000066400000000000000000000103441455764576500403770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.subpackage.SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase; /** * Integration tests that explicitly demonstrate the overriding and superseding * rules for lifecycle methods in the {@link JupiterTestEngine}. * * @since 5.9 */ class LifecycleMethodOverridingAndSupersedingTests { @Nested @DisplayName("A package-private lifecycle super-method can be overridden by") class PackagePrivateSuperClassTests { @Nested @DisplayName("a protected lifecycle method in the derived class") class ProtectedExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodTestCase { @Override @BeforeEach protected void beforeEach() { } } @Nested @DisplayName("a package-private lifecycle method in the derived class") class PackagePrivateExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodTestCase { @Override @BeforeEach void beforeEach() { } } @Nested @DisplayName("a public lifecycle method in the derived class") class PublicExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodTestCase { @Override @BeforeEach public void beforeEach() { } } } @Nested @DisplayName("A package-private lifecycle super-method from a different package can be superseded by") class PackagePrivateSuperClassInDifferentPackageTests { @Nested @DisplayName("a protected lifecycle method in the derived class") class ProtectedExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase { // @Override @BeforeEach protected void beforeEach() { } } @Nested @DisplayName("a package-private lifecycle method in the derived class") class PackagePrivateExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase { // @Override @BeforeEach void beforeEach() { } } @Nested @DisplayName("a public lifecycle method in the derived class") class PublicExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase { // @Override @BeforeEach public void beforeEach() { } } } @Nested @DisplayName("A protected lifecycle super-method can be overridden by") class ProtectedSuperClassTests { @Nested @DisplayName("a protected lifecycle method in the derived class") class ProtectedExtendsPackagePrivate extends SuperClassWithProtectedLifecycleMethodTestCase { @Override @BeforeEach protected void beforeEach() { } } @Nested @DisplayName("a public lifecycle method in the derived class") class PublicExtendsPackagePrivate extends SuperClassWithProtectedLifecycleMethodTestCase { @Override @BeforeEach public void beforeEach() { } } } @Nested @DisplayName("A public lifecycle super-method can be overridden by") class PublicSuperClassTests { @Nested @DisplayName("a public lifecycle method in the derived class") class PublicExtendsPackagePrivate extends SuperClassWithPublicLifecycleMethodTestCase { @Override @BeforeEach public void beforeEach() { } } } } // ------------------------------------------------------------------------- class SuperClassWithPackagePrivateLifecycleMethodTestCase { @BeforeEach void beforeEach() { fail(); } @Test void test() { } } class SuperClassWithProtectedLifecycleMethodTestCase { @BeforeEach protected void beforeEach() { fail(); } @Test void test() { } } class SuperClassWithPublicLifecycleMethodTestCase { @BeforeEach public void beforeEach() { fail(); } @Test void test() { } } MultipleTestableAnnotationsTests.java000066400000000000000000000031451455764576500361500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; /** * Integration tests that verify the correct behavior for methods annotated * with multiple testable annotations simultaneously. * * @since 5.0 */ @TrackLogRecords class MultipleTestableAnnotationsTests extends AbstractJupiterTestEngineTests { @Test void testAndRepeatedTest(LogRecordListener listener) { discoverTests(request().selectors(selectClass(TestCase.class)).build()); // @formatter:off assertTrue(listener.stream(Level.WARNING) .map(LogRecord::getMessage) .anyMatch(m -> m.matches("Possible configuration error: method .+ resulted in multiple TestDescriptors .+"))); // @formatter:on } static class TestCase { @Test @RepeatedTest(1) void testAndRepeatedTest(RepetitionInfo repetitionInfo) { } } } NestedTestClassesTests.java000066400000000000000000000266251455764576500340630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.util.Throwables.getRootCause; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass; import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass.RecursiveNestedClass; import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass.RecursiveNestedSiblingClass; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests that verify support for {@linkplain Nested nested contexts} * in the {@link JupiterTestEngine}. * * @since 5.0 */ class NestedTestClassesTests extends AbstractJupiterTestEngineTests { @Test void nestedTestsAreCorrectlyDiscovered() { LauncherDiscoveryRequest request = request().selectors(selectClass(TestCaseWithNesting.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(5, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void nestedTestsAreExecuted() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithNesting.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(3, tests.started().count(), "# tests started"); assertEquals(2, tests.succeeded().count(), "# tests succeeded"); assertEquals(1, tests.failed().count(), "# tests failed"); assertEquals(3, containers.started().count(), "# containers started"); assertEquals(3, containers.finished().count(), "# containers finished"); } @Test void doublyNestedTestsAreCorrectlyDiscovered() { LauncherDiscoveryRequest request = request().selectors(selectClass(TestCaseWithDoubleNesting.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(8, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void doublyNestedTestsAreExecuted() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithDoubleNesting.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(5, tests.started().count(), "# tests started"); assertEquals(3, tests.succeeded().count(), "# tests succeeded"); assertEquals(2, tests.failed().count(), "# tests failed"); assertEquals(4, containers.started().count(), "# containers started"); assertEquals(4, containers.finished().count(), "# containers finished"); assertAll("before each counts", // () -> assertEquals(5, TestCaseWithDoubleNesting.beforeTopCount), () -> assertEquals(4, TestCaseWithDoubleNesting.beforeNestedCount), () -> assertEquals(2, TestCaseWithDoubleNesting.beforeDoublyNestedCount)); assertAll("after each counts", // () -> assertEquals(5, TestCaseWithDoubleNesting.afterTopCount), () -> assertEquals(4, TestCaseWithDoubleNesting.afterNestedCount), () -> assertEquals(2, TestCaseWithDoubleNesting.afterDoublyNestedCount)); } @Test void inheritedNestedTestsAreExecuted() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithInheritedNested.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(3, tests.started().count(), "# tests started"); assertEquals(2, tests.succeeded().count(), "# tests succeeded"); assertEquals(1, tests.failed().count(), "# tests failed"); assertEquals(4, containers.started().count(), "# containers started"); assertEquals(4, containers.finished().count(), "# containers finished"); } @Test void extendedNestedTestsAreExecuted() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithExtendedNested.class); executionResults.allEvents().debug(); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(6, tests.started().count(), "# tests started"); assertEquals(4, tests.succeeded().count(), "# tests succeeded"); assertEquals(2, tests.failed().count(), "# tests failed"); assertEquals(8, containers.started().count(), "# containers started"); assertEquals(8, containers.finished().count(), "# containers finished"); } @Test void deeplyNestedInheritedMethodsAreExecutedWhenSelectedViaUniqueId() { EngineExecutionResults executionResults = executeTests(selectUniqueId( "[engine:junit-jupiter]/[class:org.junit.jupiter.engine.NestedTestClassesTests$TestCaseWithExtendedNested]/[nested-class:ConcreteInner1]/[nested-class:NestedInAbstractClass]/[nested-class:SecondLevelInherited]/[method:test()]"), selectUniqueId( "[engine:junit-jupiter]/[class:org.junit.jupiter.engine.NestedTestClassesTests$TestCaseWithExtendedNested]/[nested-class:ConcreteInner2]/[nested-class:NestedInAbstractClass]/[nested-class:SecondLevelInherited]/[method:test()]")); executionResults.allEvents().debug(); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(2, tests.started().count(), "# tests started"); assertEquals(2, tests.succeeded().count(), "# tests succeeded"); assertEquals(0, tests.failed().count(), "# tests failed"); assertEquals(8, containers.started().count(), "# containers started"); assertEquals(8, containers.finished().count(), "# containers finished"); } /** * @since 1.6 */ @Test void recursiveNestedTestClassHierarchiesAreNotExecuted() { assertNestedCycle(OuterClass.class, RecursiveNestedClass.class, OuterClass.class); assertNestedCycle(NestedClass.class, RecursiveNestedClass.class, OuterClass.class); assertNestedCycle(RecursiveNestedClass.class, RecursiveNestedClass.class, OuterClass.class); } /** * NOTE: We do not actually support this as a feature, but we currently only * check for cycles if a class is selected. Thus, the tests in this method * pass, since the selection of a particular method does not result in a * lookup for nested test classes. * * @since 1.6 */ @Test void individualMethodsWithinRecursiveNestedTestClassHierarchiesAreExecuted() { EngineExecutionResults executionResults = executeTests(selectMethod(OuterClass.class, "outer")); executionResults.containerEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); executionResults.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); executionResults = executeTests(selectMethod(NestedClass.class, "nested")); executionResults.containerEvents().assertStatistics(stats -> stats.started(3).succeeded(3)); executionResults.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); executionResults = executeTests(selectMethod(RecursiveNestedClass.class, "nested")); executionResults.containerEvents().assertStatistics(stats -> stats.started(4).succeeded(4)); executionResults.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); executionResults = executeTests(selectMethod(RecursiveNestedSiblingClass.class, "nested")); executionResults.containerEvents().assertStatistics(stats -> stats.started(4).succeeded(4)); executionResults.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); } private void assertNestedCycle(Class start, Class from, Class to) { assertThatExceptionOfType(JUnitException.class)// .isThrownBy(() -> executeTestsForClass(start))// .withCauseExactlyInstanceOf(JUnitException.class)// .satisfies(ex -> assertThat(getRootCause(ex)).hasMessageMatching( String.format("Detected cycle in inner class hierarchy between .+%s and .+%s", from.getSimpleName(), to.getSimpleName()))); } // ------------------------------------------------------------------- static class TestCaseWithNesting { @Test void someTest() { } @Nested class NestedTestCase { @Test void successful() { } @Test void failing() { Assertions.fail("Something went horribly wrong"); } } } static class TestCaseWithDoubleNesting { static int beforeTopCount = 0; static int beforeNestedCount = 0; static int beforeDoublyNestedCount = 0; static int afterTopCount = 0; static int afterNestedCount = 0; static int afterDoublyNestedCount = 0; @BeforeEach void beforeTop() { beforeTopCount++; } @AfterEach void afterTop() { afterTopCount++; } @Test void someTest() { } @Nested class NestedTestCase { @BeforeEach void beforeNested() { beforeNestedCount++; } @AfterEach void afterNested() { afterNestedCount++; } @Test void successful() { } @Test void failing() { Assertions.fail("Something went horribly wrong"); } @Nested class DoublyNestedTestCase { @BeforeEach void beforeDoublyNested() { beforeDoublyNestedCount++; } @BeforeEach void afterDoublyNested() { afterDoublyNestedCount++; } @Test void successful() { } @Test void failing() { Assertions.fail("Something went horribly wrong"); } } } } interface InterfaceWithNestedClass { @Nested class NestedInInterface { @Test void notExecutedByImplementingClass() { Assertions.fail("class in interface is static and should have been filtered out"); } } } static abstract class AbstractSuperClass implements InterfaceWithNestedClass { @Nested class NestedInAbstractClass { @Test void successful() { } @Test void failing() { Assertions.fail("something went wrong"); } @Nested class SecondLevelInherited { @Test void test() { } } } } static class TestCaseWithInheritedNested extends AbstractSuperClass { // empty on purpose } static class TestCaseWithExtendedNested { @Nested class ConcreteInner1 extends AbstractSuperClass { } @Nested class ConcreteInner2 extends AbstractSuperClass { } } static class AbstractOuterClass { } static class OuterClass extends AbstractOuterClass { @Test void outer() { } @Nested class NestedClass { @Test void nested() { } @Nested class RecursiveNestedClass extends OuterClass { @Test void nested() { } } @Nested // sibling of OuterClass due to common super type class RecursiveNestedSiblingClass extends AbstractOuterClass { @Test void nested() { } } } } } NestedWithInheritanceTests.java000066400000000000000000000031171455764576500347020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; class NestedWithInheritanceTests extends SuperClass { static List lifecycleInvokingClassNames; static String OUTER = NestedWithInheritanceTests.class.getSimpleName(); static String NESTED = NestedClass.class.getSimpleName(); static String NESTEDNESTED = NestedClass.NestedNestedClass.class.getSimpleName(); @Nested class NestedClass extends SuperClass { @Test public void test() { assertThat(lifecycleInvokingClassNames).containsExactly(OUTER, NESTED); } @Nested class NestedNestedClass extends SuperClass { @Test public void test() { assertThat(lifecycleInvokingClassNames).containsExactly(OUTER, NESTED, NESTEDNESTED); } } } } class SuperClass { @BeforeAll static void setup() { NestedWithInheritanceTests.lifecycleInvokingClassNames = new ArrayList<>(); } @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); NestedWithInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); } } NestedWithSeparateInheritanceTests.java000066400000000000000000000044251455764576500363720ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; class NestedWithSeparateInheritanceTests extends SuperClass1 { static List lifecycleInvokingClassNames; static String OUTER = NestedWithSeparateInheritanceTests.class.getSimpleName(); static String NESTED = NestedClass.class.getSimpleName(); static String NESTEDNESTED = NestedClass.NestedNestedClass.class.getSimpleName(); @Nested class NestedClass extends SuperClass2 { @Test public void test() { assertThat(lifecycleInvokingClassNames).containsExactly(OUTER, NESTED); } @Nested class NestedNestedClass extends SuperClass3 { @Test public void test() { assertThat(lifecycleInvokingClassNames).containsExactly(OUTER, NESTED, NESTEDNESTED); } } } } class SuperClass1 { @BeforeAll static void setup() { NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames = new ArrayList<>(); } @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); } } class SuperClass2 { @BeforeAll static void setup() { NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames = new ArrayList<>(); } @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); } } class SuperClass3 { @BeforeAll static void setup() { NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames = new ArrayList<>(); } @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); } } NonVoidTestableMethodIntegrationTests.java000066400000000000000000000016461455764576500370640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; class NonVoidTestableMethodIntegrationTests { @Test void valid() { } @Test int invalidMethodReturningPrimitive() { fail("This method should never have been called."); return 1; } @Test String invalidMethodReturningObject() { fail("This method should never have been called."); return ""; } @RepeatedTest(3) int invalidMethodVerifyingTestTemplateMethod() { fail("This method should never have been called."); return 1; } } OverloadedTestMethodTests.java000066400000000000000000000051601455764576500345370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.testkit.engine.Event; import org.junit.platform.testkit.engine.Events; /** * Integration tests for support of overloaded test methods in conjunction with * the {@link JupiterTestEngine}. * * @since 5.0 */ class OverloadedTestMethodTests extends AbstractJupiterTestEngineTests { @Test void executeTestCaseWithOverloadedMethodsAndThenRerunOnlyOneOfTheMethodsSelectedByUniqueId() { Events tests = executeTestsForClass(TestCase.class).testEvents(); tests.assertStatistics(stats -> stats.started(2).succeeded(2).failed(0)); Optional first = tests.succeeded().filter( event -> event.getTestDescriptor().getUniqueId().toString().contains(TestInfo.class.getName())).findFirst(); assertTrue(first.isPresent()); TestIdentifier testIdentifier = TestIdentifier.from(first.get().getTestDescriptor()); UniqueId uniqueId = testIdentifier.getUniqueIdObject(); tests = executeTests(selectUniqueId(uniqueId)).testEvents(); tests.assertStatistics(stats -> stats.started(1).succeeded(1).failed(0)); first = tests.succeeded().filter( event -> event.getTestDescriptor().getUniqueId().toString().contains(TestInfo.class.getName())).findFirst(); assertTrue(first.isPresent()); } @Test void executeTestCaseWithOverloadedMethodsWithSingleMethodThatAcceptsArgumentsSelectedByFullyQualifedMethodName() { String fqmn = TestCase.class.getName() + "#test(" + TestInfo.class.getName() + ")"; Events tests = executeTests(selectMethod(fqmn)).testEvents(); tests.assertStatistics(stats -> stats.started(1).succeeded(1).failed(0)); Optional first = tests.succeeded().stream().filter( event -> event.getTestDescriptor().getUniqueId().toString().contains(TestInfo.class.getName())).findFirst(); assertTrue(first.isPresent()); } static class TestCase { @Test void test() { } @Test void test(TestInfo testInfo) { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/RecordTests.java000066400000000000000000000015561455764576500317540ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; class RecordTests extends AbstractJupiterTestEngineTests { @Test void recordsAreTestClasses() { executeTestsForClass(TestCase.class).testEvents() // .assertStatistics(stats -> stats.finished(2).succeeded(1).failed(1)); } record TestCase() { @Test void succeedingTest() { assertTrue(true); } @Test void failingTest() { fail("always fails"); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/ReportingTests.java000066400000000000000000000043651455764576500325100ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.util.Collections.emptyMap; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestReporter; import org.junit.platform.commons.PreconditionViolationException; /** * @since 5.0 */ class ReportingTests extends AbstractJupiterTestEngineTests { @Test void reportEntriesArePublished() { executeTestsForClass(MyReportingTestCase.class).testEvents().assertStatistics(stats -> stats // .started(2) // .succeeded(2) // .failed(0) // .reportingEntryPublished(7)); } static class MyReportingTestCase { @BeforeEach void beforeEach(TestReporter reporter) { reporter.publishEntry("@BeforeEach"); } @AfterEach void afterEach(TestReporter reporter) { reporter.publishEntry("@AfterEach"); } @Test void succeedingTest(TestReporter reporter) { reporter.publishEntry(emptyMap()); reporter.publishEntry("user name", "dk38"); reporter.publishEntry("message"); } @Test void invalidReportData(TestReporter reporter) { // Maps Map map = new HashMap<>(); map.put("key", null); assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry(map)); map.clear(); map.put(null, "value"); assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry(map)); assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry((Map) null)); // Key-Value pair assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry(null, "bar")); assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry("foo", null)); // Value assertThrows(PreconditionViolationException.class, () -> reporter.publishEntry((String) null)); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/SealedClassTests.java000066400000000000000000000017521455764576500327170ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; class SealedClassTests extends AbstractJupiterTestEngineTests { @Test void sealedTestClassesAreTestClasses() { executeTestsForClass(TestCase.class).testEvents() // .assertStatistics(stats -> stats.finished(2).succeeded(1).failed(1)); } sealed abstract static class AbstractTestCase permits TestCase { @Test void succeedingTest() { assertTrue(true); } @Test void failingTest() { fail("always fails"); } } static final class TestCase extends AbstractTestCase { } } StandardTestClassTests.java000066400000000000000000000154641455764576500340500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; import org.opentest4j.TestAbortedException; /** * Tests for discovery and execution of standard test cases for the * {@link JupiterTestEngine}. * * @since 5.0 */ class StandardTestClassTests extends AbstractJupiterTestEngineTests { @Test void standardTestClassIsCorrectlyDiscovered() { LauncherDiscoveryRequest request = request().selectors(selectClass(MyStandardTestCase.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(1 /*class*/ + 6 /*methods*/, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void moreThanOneTestClassIsCorrectlyDiscovered() { LauncherDiscoveryRequest request = request().selectors(selectClass(SecondOfTwoTestCases.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(1 /*class*/ + 3 /*methods*/, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void moreThanOneTestClassIsExecuted() { LauncherDiscoveryRequest request = request().selectors(selectClass(FirstOfTwoTestCases.class), selectClass(SecondOfTwoTestCases.class)).build(); EngineExecutionResults executionResults = executeTests(request); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(6, tests.started().count(), "# tests started"); assertEquals(5, tests.succeeded().count(), "# tests succeeded"); assertEquals(1, tests.failed().count(), "# tests failed"); assertEquals(3, containers.started().count(), "# containers started"); assertEquals(3, containers.finished().count(), "# containers finished"); } @Test void allTestsInClassAreRunWithBeforeEachAndAfterEachMethods() { EngineExecutionResults executionResults = executeTestsForClass(MyStandardTestCase.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(2, containers.started().count(), "# containers started"); assertEquals(2, containers.finished().count(), "# containers finished"); assertEquals(6, tests.started().count(), "# tests started"); assertEquals(2, tests.succeeded().count(), "# tests succeeded"); assertEquals(3, tests.aborted().count(), "# tests aborted"); assertEquals(1, tests.failed().count(), "# tests failed"); assertEquals(6, MyStandardTestCase.countBefore1, "# before1 calls"); assertEquals(6, MyStandardTestCase.countBefore2, "# before2 calls"); assertEquals(6, MyStandardTestCase.countAfter, "# after each calls"); } @Test void testsFailWhenBeforeEachFails() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithFailingBefore.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(2, tests.started().count(), "# tests started"); assertEquals(0, tests.succeeded().count(), "# tests succeeded"); assertEquals(2, tests.failed().count(), "# tests failed"); assertEquals(2, containers.started().count(), "# containers started"); assertEquals(2, containers.finished().count(), "# containers finished"); assertEquals(2, TestCaseWithFailingBefore.countBefore, "# before each calls"); } @Test void testsFailWhenAfterEachFails() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithFailingAfter.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); assertEquals(1, tests.started().count(), "# tests started"); assertEquals(0, tests.succeeded().count(), "# tests succeeded"); assertEquals(1, tests.failed().count(), "# tests failed"); assertEquals(2, containers.started().count(), "# containers started"); assertEquals(2, containers.finished().count(), "# containers finished"); assertTrue(TestCaseWithFailingAfter.testExecuted, "test executed?"); } static class MyStandardTestCase { static int countBefore1 = 0; static int countBefore2 = 0; static int countAfter = 0; @BeforeEach void before1() { countBefore1++; } @BeforeEach void before2() { countBefore2++; } @AfterEach void after() { countAfter++; } @Test void succeedingTest1() { assertTrue(true); } @Test void succeedingTest2() { assertTrue(true); } @Test void failingTest() { fail("always fails"); } @Test @DisplayName("Test aborted via the OTA's TestAbortedException") void testAbortedOpenTest4J() { throw new TestAbortedException("aborted!"); } @Test @DisplayName("Test aborted via JUnit 4's AssumptionViolatedException") void testAbortedJUnit4() { throw new org.junit.AssumptionViolatedException("aborted!"); } @Test @DisplayName("Test aborted via JUnit 4's legacy, deprecated AssumptionViolatedException") @SuppressWarnings("deprecation") void testAbortedJUnit4Legacy() { throw new org.junit.internal.AssumptionViolatedException("aborted!"); } } static class FirstOfTwoTestCases { @Test void succeedingTest1() { assertTrue(true); } @Test void succeedingTest2() { assertTrue(true); } @Test void failingTest() { fail("always fails"); } } static class SecondOfTwoTestCases { @Test void succeedingTest1() { assertTrue(true); } @Test void succeedingTest2() { assertTrue(true); } @Test void succeedingTest3() { assertTrue(true); } } static class TestCaseWithFailingBefore { static int countBefore = 0; @BeforeEach void before() { countBefore++; throw new RuntimeException("Problem during setup"); } @Test void test1() { } @Test void test2() { } } static class TestCaseWithFailingAfter { static boolean testExecuted = false; @AfterEach void after() { throw new RuntimeException("Problem during 'after'"); } @Test void test1() { testExecuted = true; } } } StaticNestedBeforeAllAndAfterAllMethodsTests.java000066400000000000000000000046541455764576500402110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; /** * Integration tests that verify support for {@code static} {@link BeforeAll} and * {@link AfterAll} methods in {@link Nested} tests on Java 16+. * * @since 5.9 * @see BeforeAllAndAfterAllComposedAnnotationTests */ class StaticNestedBeforeAllAndAfterAllMethodsTests extends AbstractJupiterTestEngineTests { private static final List methodsInvoked = new ArrayList<>(); @DisplayName("static @BeforeAll and @AfterAll methods in @Nested test class") @Test void staticBeforeAllAndAfterAllMethodsInNestedTestClass() { executeTestsForClass(TestCase.class).testEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); assertThat(methodsInvoked).containsExactly(// "@BeforeAll: top-level", // "@Test: top-level", // "@BeforeAll: nested", // "@Test: nested", // "@AfterAll: nested", // "@AfterAll: top-level"// ); } static class TestCase { @BeforeAll static void beforeAll() { methodsInvoked.add("@BeforeAll: top-level"); } @Test void test() { methodsInvoked.add("@Test: top-level"); } @AfterAll static void afterAll() { methodsInvoked.add("@AfterAll: top-level"); } @Nested // Lifecycle.PER_METHOD is the default, but we declare it here in order // to be very explicit about what we are testing, namely static lifecycle // methods in an inner class WITHOUT Lifecycle.PER_CLASS semantics. @TestInstance(Lifecycle.PER_METHOD) class NestedTestCase { @BeforeAll static void beforeAllInner() { methodsInvoked.add("@BeforeAll: nested"); } @Test void test() { methodsInvoked.add("@Test: nested"); } @AfterAll static void afterAllInner() { methodsInvoked.add("@AfterAll: nested"); } } } } TestClassInheritanceTests.java000066400000000000000000000174601455764576500345370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for test class hierarchy support in the {@link JupiterTestEngine}. * * @since 5.0 */ class TestClassInheritanceTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @BeforeEach void initStatics() { callSequence.clear(); LocalTestCase.countBeforeInvoked = 0; LocalTestCase.countAfterInvoked = 0; AbstractTestCase.countSuperBeforeInvoked = 0; AbstractTestCase.countSuperAfterInvoked = 0; } @Test void executeAllTestsInClass() { EngineExecutionResults executionResults = executeTestsForClass(LocalTestCase.class); assertEquals(6, executionResults.testEvents().started().count(), "# tests started"); assertEquals(3, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(1, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(2, executionResults.testEvents().failed().count(), "# tests failed"); assertEquals(6, LocalTestCase.countBeforeInvoked, "# before calls"); assertEquals(6, LocalTestCase.countAfterInvoked, "# after calls"); assertEquals(6, AbstractTestCase.countSuperBeforeInvoked, "# super before calls"); assertEquals(6, AbstractTestCase.countSuperAfterInvoked, "# super after calls"); } @Test void executeSingleTest() { EngineExecutionResults executionResults = executeTests(selectMethod(LocalTestCase.class, "alwaysPasses")); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestDeclaredInSuperClass() { EngineExecutionResults executionResults = executeTests(selectMethod(LocalTestCase.class, "superTest")); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); assertEquals(1, LocalTestCase.countBeforeInvoked, "# after calls"); assertEquals(1, LocalTestCase.countAfterInvoked, "# after calls"); assertEquals(1, AbstractTestCase.countSuperBeforeInvoked, "# super before calls"); assertEquals(1, AbstractTestCase.countSuperAfterInvoked, "# super after calls"); } @Test void executeTestWithExceptionThrownInAfterMethod() { EngineExecutionResults executionResults = executeTests( selectMethod(LocalTestCase.class, "throwExceptionInAfterMethod")); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void beforeAndAfterMethodsInTestClassHierarchy() { EngineExecutionResults executionResults = executeTestsForClass(TestCase3.class); // @formatter:off assertAll( () -> assertEquals(1, executionResults.testEvents().started().count(), "# tests started"), () -> assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"), () -> assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"), () -> assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"), () -> assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed") ); // @formatter:on // @formatter:off assertEquals(asList( "beforeAll1", "beforeAll2", "beforeAll3", "beforeEach1", "beforeEach2", "beforeEach3", "test3", "afterEach3", "afterEach2", "afterEach1", "afterAll3", "afterAll2", "afterAll1" ), callSequence, "wrong call sequence"); // @formatter:on } // ------------------------------------------------------------------- private static abstract class AbstractTestCase { static int countSuperBeforeInvoked = 0; static int countSuperAfterInvoked = 0; @BeforeEach void superBefore() { countSuperBeforeInvoked++; } @AfterEach void superAfter() { countSuperAfterInvoked++; } @Test void superTest() { /* no-op */ } } static class LocalTestCase extends AbstractTestCase { boolean throwExceptionInAfterMethod = false; static int countBeforeInvoked = 0; static int countAfterInvoked = 0; @BeforeEach void before() { countBeforeInvoked++; // Reset state, since the test instance is retained across all test methods; // otherwise, after() always throws an exception. this.throwExceptionInAfterMethod = false; } @AfterEach void after() { countAfterInvoked++; if (this.throwExceptionInAfterMethod) { throw new RuntimeException("Exception thrown from @AfterEach method"); } } @Test void otherTest() { /* no-op */ } @Test void throwExceptionInAfterMethod() { this.throwExceptionInAfterMethod = true; } @Test void alwaysPasses() { /* no-op */ } @Test void aborted() { assumeTrue(false); } @Test void alwaysFails() { fail("#fail"); } } static class TestCase1 { @BeforeAll static void beforeAll1() { callSequence.add("beforeAll1"); } @BeforeEach void beforeEach1() { callSequence.add("beforeEach1"); } @AfterEach void afterEach1() { callSequence.add("afterEach1"); } @AfterAll static void afterAll1() { callSequence.add("afterAll1"); } } static class TestCase2 extends TestCase1 { @BeforeAll static void beforeAll2() { callSequence.add("beforeAll2"); } @BeforeEach void beforeEach2() { callSequence.add("beforeEach2"); } @AfterEach void afterEach2() { callSequence.add("afterEach2"); } @AfterAll static void afterAll2() { callSequence.add("afterAll2"); } } static class TestCase3 extends TestCase2 { @BeforeAll static void beforeAll3() { callSequence.add("beforeAll3"); } @BeforeEach void beforeEach3() { callSequence.add("beforeEach3"); } @Test void test3() { callSequence.add("test3"); } @AfterEach void afterEach3() { callSequence.add("afterEach3"); } @AfterAll static void afterAll3() { callSequence.add("afterAll3"); } } } TestInstanceLifecycleConfigurationTests.java000066400000000000000000000152501455764576500374270ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.launcher.Launcher; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for {@link TestInstance @TestInstance} lifecycle * configuration support, not to be confused with {@link TestInstanceLifecycleTests}. * *

Specifically, this class tests custom lifecycle configuration specified * via {@code @TestInstance} as well as via {@link ConfigurationParameters} * supplied to the {@link Launcher} or via a JVM system property. * * @since 5.0 * @see TestInstanceLifecycleTests */ class TestInstanceLifecycleConfigurationTests extends AbstractJupiterTestEngineTests { private static final String KEY = Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; private static final List methodsInvoked = new ArrayList<>(); @BeforeEach @AfterEach void reset() { methodsInvoked.clear(); System.clearProperty(KEY); } @Test void instancePerMethodUsingStandardDefaultConfiguration() { performAssertions(AssumedInstancePerTestMethodTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerClassConfiguredViaExplicitAnnotationDeclaration() { performAssertions(ExplicitInstancePerClassTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerClassConfiguredViaSystemProperty() { Class testClass = AssumedInstancePerClassTestCase.class; // Should fail by default... performAssertions(testClass, 2, 1, 0); // Should pass with the system property set System.setProperty(KEY, PER_CLASS.name()); performAssertions(testClass, 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerClassConfiguredViaConfigParam() { Class testClass = AssumedInstancePerClassTestCase.class; // Should fail by default... performAssertions(testClass, 2, 1, 0); // Should pass with the config param performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerClassConfiguredViaConfigParamThatOverridesSystemProperty() { Class testClass = AssumedInstancePerClassTestCase.class; // Should fail with system property System.setProperty(KEY, PER_METHOD.name()); performAssertions(testClass, 2, 1, 0); // Should pass with the config param performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerMethodConfiguredViaExplicitAnnotationDeclarationThatOverridesSystemProperty() { System.setProperty(KEY, PER_CLASS.name()); performAssertions(ExplicitInstancePerTestMethodTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll"); } @Test void instancePerMethodConfiguredViaExplicitAnnotationDeclarationThatOverridesConfigParam() { Class testClass = ExplicitInstancePerTestMethodTestCase.class; performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll"); } private void performAssertions(Class testClass, int containers, int containersFailed, int tests, String... methods) { performAssertions(testClass, emptyMap(), containers, containersFailed, tests, methods); } private void performAssertions(Class testClass, Map configParams, int numContainers, int numFailedContainers, int numTests, String... methods) { // @formatter:off EngineExecutionResults executionResults = executeTests( request() .selectors(selectClass(testClass)) .configurationParameters(configParams) .build() ); // @formatter:on executionResults.containerEvents().assertStatistics(// stats -> stats.started(numContainers).finished(numContainers).failed(numFailedContainers)); executionResults.testEvents().assertStatistics(// stats -> stats.started(numTests).finished(numTests)); assertEquals(Arrays.asList(methods), methodsInvoked); } // ------------------------------------------------------------------------- @TestInstance(PER_METHOD) static class ExplicitInstancePerTestMethodTestCase { @BeforeAll static void beforeAll() { methodsInvoked.add("beforeAll"); } @Test void test() { methodsInvoked.add("test"); } @AfterAll static void afterAllStatic() { methodsInvoked.add("afterAll"); } } /** * "per-method" lifecycle mode is assumed since the {@code @BeforeAll} and * {@code @AfterAll} methods are static, even though there is no explicit * {@code @TestInstance} declaration. */ static class AssumedInstancePerTestMethodTestCase { @BeforeAll static void beforeAll() { methodsInvoked.add("beforeAll"); } @Test void test() { methodsInvoked.add("test"); } @AfterAll static void afterAllStatic() { methodsInvoked.add("afterAll"); } } @TestInstance(PER_CLASS) static class ExplicitInstancePerClassTestCase { @BeforeAll void beforeAll(TestInfo testInfo) { methodsInvoked.add("beforeAll"); } @Test void test() { methodsInvoked.add("test"); } @AfterAll void afterAll(TestInfo testInfo) { methodsInvoked.add("afterAll"); } } /** * "per-class" lifecycle mode is assumed since the {@code @BeforeAll} and * {@code @AfterAll} methods are non-static, even though there is no * explicit {@code @TestInstance} declaration. */ static class AssumedInstancePerClassTestCase { @BeforeAll void beforeAll(TestInfo testInfo) { methodsInvoked.add("beforeAll"); } @Test void test() { methodsInvoked.add("test"); } @AfterAll void afterAll(TestInfo testInfo) { methodsInvoked.add("afterAll"); } } } TestInstanceLifecycleKotlinTests.java000066400000000000000000000057671455764576500360740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.engine.kotlin.InstancePerClassKotlinTestCase; import org.junit.jupiter.engine.kotlin.InstancePerMethodKotlinTestCase; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Kotlin-specific integration tests for {@link TestInstance @TestInstance} * lifecycle support. * * @since 5.1 * @see TestInstanceLifecycleConfigurationTests * @see TestInstanceLifecycleTests */ class TestInstanceLifecycleKotlinTests extends AbstractJupiterTestEngineTests { @Test void instancePerClassCanBeUsedForKotlinTestClasses() { Class testClass = InstancePerClassKotlinTestCase.class; InstancePerClassKotlinTestCase.TEST_INSTANCES.clear(); EngineExecutionResults executionResults = executeTestsForClass(testClass); assertThat(executionResults.testEvents().finished().count()).isEqualTo(2); assertThat(InstancePerClassKotlinTestCase.TEST_INSTANCES.keySet()).hasSize(1); assertThat(getOnlyElement(InstancePerClassKotlinTestCase.TEST_INSTANCES.values())) // .containsEntry("beforeAll", 1) // .containsEntry("beforeEach", 2) // .containsEntry("test", 2) // .containsEntry("afterEach", 2) // .containsEntry("afterAll", 1); } @Test void instancePerMethodIsDefaultForKotlinTestClasses() { Class testClass = InstancePerMethodKotlinTestCase.class; InstancePerMethodKotlinTestCase.TEST_INSTANCES.clear(); EngineExecutionResults executionResults = executeTestsForClass(testClass); assertThat(executionResults.testEvents().finished().count()).isEqualTo(2); List instances = new ArrayList<>(InstancePerMethodKotlinTestCase.TEST_INSTANCES.keySet()); assertThat(instances) // .hasSize(3) // .extracting(o -> (Object) o.getClass()) // .containsExactly(InstancePerMethodKotlinTestCase.Companion.getClass(), // InstancePerMethodKotlinTestCase.class, // InstancePerMethodKotlinTestCase.class); assertThat(InstancePerMethodKotlinTestCase.TEST_INSTANCES.get(instances.get(0))) // .containsEntry("beforeAll", 1) // .containsEntry("afterAll", 1); assertThat(InstancePerMethodKotlinTestCase.TEST_INSTANCES.get(instances.get(1))) // .containsEntry("beforeEach", 1) // .containsEntry("test", 1) // .containsEntry("afterEach", 1); assertThat(InstancePerMethodKotlinTestCase.TEST_INSTANCES.get(instances.get(2))) // .containsEntry("beforeEach", 1) // .containsEntry("test", 1) // .containsEntry("afterEach", 1); } } TestInstanceLifecycleTests.java000066400000000000000000001313521455764576500347010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.lang.String.join; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.engine.execution.DefaultTestInstances; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for {@link TestInstance @TestInstance} lifecycle support. * * @since 5.0 * @see TestInstanceLifecycleConfigurationTests * @see TestInstanceLifecycleKotlinTests */ class TestInstanceLifecycleTests extends AbstractJupiterTestEngineTests { private static final Map, List> lifecyclesMap = new LinkedHashMap<>(); private static final Map instanceMap = new LinkedHashMap<>(); private static final List testsInvoked = new ArrayList<>(); private static final Map, Integer> instanceCount = new LinkedHashMap<>(); private static int beforeAllCount; private static int afterAllCount; private static int beforeEachCount; private static int afterEachCount; @BeforeEach void init() { lifecyclesMap.clear(); instanceMap.clear(); testsInvoked.clear(); instanceCount.clear(); beforeAllCount = 0; afterAllCount = 0; beforeEachCount = 0; afterEachCount = 0; } @Test void instancePerMethod() { Class testClass = InstancePerMethodTestCase.class; int containers = 3; int tests = 3; Map.Entry, Integer>[] instances = instanceCounts(entry(InstancePerMethodTestCase.class, 3)); int allMethods = 1; int eachMethods = 3; performAssertions(testClass, containers, tests, instances, allMethods, eachMethods); String containerExecutionConditionKey = executionConditionKey(testClass, null); String postProcessTestInstanceKey = postProcessTestInstanceKey(testClass); String preDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(testClass); String beforeAllCallbackKey = beforeAllCallbackKey(testClass); String afterAllCallbackKey = afterAllCallbackKey(testClass); String testTemplateKey = testTemplateKey(testClass, "singletonTest"); String testExecutionConditionKey1 = executionConditionKey(testClass, testsInvoked.get(0)); String beforeEachCallbackKey1 = beforeEachCallbackKey(testClass, testsInvoked.get(0)); String afterEachCallbackKey1 = afterEachCallbackKey(testClass, testsInvoked.get(0)); String testExecutionConditionKey2 = executionConditionKey(testClass, testsInvoked.get(1)); String beforeEachCallbackKey2 = beforeEachCallbackKey(testClass, testsInvoked.get(1)); String afterEachCallbackKey2 = afterEachCallbackKey(testClass, testsInvoked.get(1)); String testExecutionConditionKey3 = executionConditionKey(testClass, testsInvoked.get(2)); String beforeEachCallbackKey3 = beforeEachCallbackKey(testClass, testsInvoked.get(2)); String afterEachCallbackKey3 = afterEachCallbackKey(testClass, testsInvoked.get(2)); // @formatter:off assertThat(instanceMap.keySet()).containsExactlyInAnyOrder( containerExecutionConditionKey, beforeAllCallbackKey, postProcessTestInstanceKey, preDestroyCallbackTestInstanceKey, testTemplateKey, testExecutionConditionKey1, beforeEachCallbackKey1, afterEachCallbackKey1, testExecutionConditionKey2, beforeEachCallbackKey2, afterEachCallbackKey2, testExecutionConditionKey3, beforeEachCallbackKey3, afterEachCallbackKey3, afterAllCallbackKey ); // @formatter:on assertNull(instanceMap.get(containerExecutionConditionKey)); assertNull(instanceMap.get(beforeAllCallbackKey)); assertNull(instanceMap.get(afterAllCallbackKey)); TestInstances testInstances = instanceMap.get(beforeEachCallbackKey1); assertNotNull(testInstances.getInnermostInstance()); assertSame(testInstances, instanceMap.get(afterEachCallbackKey1)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey1)); testInstances = instanceMap.get(beforeEachCallbackKey2); assertNotNull(testInstances.getInnermostInstance()); assertSame(testInstances, instanceMap.get(afterEachCallbackKey2)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey2)); testInstances = instanceMap.get(beforeEachCallbackKey3); assertNotNull(testInstances.getInnermostInstance()); assertSame(testInstances, instanceMap.get(afterEachCallbackKey3)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey3)); assertSame(testInstances.getInnermostInstance(), instanceMap.get(postProcessTestInstanceKey).getInnermostInstance()); assertSame(testInstances.getInnermostInstance(), instanceMap.get(preDestroyCallbackTestInstanceKey).getInnermostInstance()); assertThat(lifecyclesMap.keySet()).containsExactly(testClass); assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_METHOD::equals); } @Test void instancePerClass() { instancePerClass(InstancePerClassTestCase.class, instanceCounts(entry(InstancePerClassTestCase.class, 1))); } @Test void instancePerClassWithInheritedLifecycleMode() { instancePerClass(SubInstancePerClassTestCase.class, instanceCounts(entry(SubInstancePerClassTestCase.class, 1))); } private void instancePerClass(Class testClass, Map.Entry, Integer>[] instances) { int containers = 3; int tests = 3; int allMethods = 2; int eachMethods = 3; performAssertions(testClass, containers, tests, instances, allMethods, eachMethods); String containerExecutionConditionKey = executionConditionKey(testClass, null); String testTemplateKey = testTemplateKey(testClass, "singletonTest"); String postProcessTestInstanceKey = postProcessTestInstanceKey(testClass); String preDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(testClass); String beforeAllCallbackKey = beforeAllCallbackKey(testClass); String afterAllCallbackKey = afterAllCallbackKey(testClass); String testExecutionConditionKey1 = executionConditionKey(testClass, testsInvoked.get(0)); String beforeEachCallbackKey1 = beforeEachCallbackKey(testClass, testsInvoked.get(0)); String afterEachCallbackKey1 = afterEachCallbackKey(testClass, testsInvoked.get(0)); String testExecutionConditionKey2 = executionConditionKey(testClass, testsInvoked.get(1)); String beforeEachCallbackKey2 = beforeEachCallbackKey(testClass, testsInvoked.get(1)); String afterEachCallbackKey2 = afterEachCallbackKey(testClass, testsInvoked.get(1)); String testExecutionConditionKey3 = executionConditionKey(testClass, testsInvoked.get(2)); String beforeEachCallbackKey3 = beforeEachCallbackKey(testClass, testsInvoked.get(2)); String afterEachCallbackKey3 = afterEachCallbackKey(testClass, testsInvoked.get(2)); // @formatter:off assertThat(instanceMap.keySet()).containsExactlyInAnyOrder( postProcessTestInstanceKey, preDestroyCallbackTestInstanceKey, containerExecutionConditionKey, beforeAllCallbackKey, testTemplateKey, testExecutionConditionKey1, beforeEachCallbackKey1, afterEachCallbackKey1, testExecutionConditionKey2, beforeEachCallbackKey2, afterEachCallbackKey2, testExecutionConditionKey3, beforeEachCallbackKey3, afterEachCallbackKey3, afterAllCallbackKey ); // @formatter:on TestInstances testInstances = instanceMap.get(beforeAllCallbackKey); assertNotNull(testInstances.getInnermostInstance()); assertSame(testInstances, instanceMap.get(afterAllCallbackKey)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey1)); assertSame(testInstances, instanceMap.get(beforeEachCallbackKey1)); assertSame(testInstances, instanceMap.get(afterEachCallbackKey1)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey2)); assertSame(testInstances, instanceMap.get(beforeEachCallbackKey2)); assertSame(testInstances, instanceMap.get(afterEachCallbackKey2)); assertSame(testInstances, instanceMap.get(testExecutionConditionKey3)); assertSame(testInstances, instanceMap.get(beforeEachCallbackKey3)); assertSame(testInstances, instanceMap.get(afterEachCallbackKey3)); assertSame(testInstances.getInnermostInstance(), instanceMap.get(postProcessTestInstanceKey).getInnermostInstance()); assertSame(testInstances.getInnermostInstance(), instanceMap.get(preDestroyCallbackTestInstanceKey).getInnermostInstance()); assertNull(instanceMap.get(containerExecutionConditionKey)); assertThat(lifecyclesMap.keySet()).containsExactly(testClass); assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); } @Test void instancePerMethodWithNestedTestClass() { Class testClass = InstancePerMethodOuterTestCase.class; Class nestedTestClass = InstancePerMethodOuterTestCase.NestedInstancePerMethodTestCase.class; int containers = 4; int tests = 4; Map.Entry, Integer>[] instances = instanceCounts(entry(testClass, 4), entry(nestedTestClass, 3)); int allMethods = 1; int eachMethods = 3; performAssertions(testClass, containers, tests, instances, allMethods, eachMethods); String containerExecutionConditionKey = executionConditionKey(testClass, null); String nestedContainerExecutionConditionKey = executionConditionKey(nestedTestClass, null); String nestedTestTemplateKey = testTemplateKey(nestedTestClass, "singletonTest"); String postProcessTestInstanceKey = postProcessTestInstanceKey(testClass); String nestedPostProcessTestInstanceKey = postProcessTestInstanceKey(nestedTestClass); String preDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(testClass); String nestedPreDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(nestedTestClass); String beforeAllCallbackKey = beforeAllCallbackKey(testClass); String afterAllCallbackKey = afterAllCallbackKey(testClass); String outerTestExecutionConditionKey = executionConditionKey(testClass, "outerTest"); String beforeEachCallbackKey = beforeEachCallbackKey(testClass, "outerTest"); String afterEachCallbackKey = afterEachCallbackKey(testClass, "outerTest"); String nestedBeforeAllCallbackKey = beforeAllCallbackKey(nestedTestClass); String nestedAfterAllCallbackKey = afterAllCallbackKey(nestedTestClass); String nestedExecutionConditionKey1 = executionConditionKey(nestedTestClass, testsInvoked.get(0)); String nestedBeforeEachCallbackKey1 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedAfterEachCallbackKey1 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedExecutionConditionKey2 = executionConditionKey(nestedTestClass, testsInvoked.get(1)); String nestedBeforeEachCallbackKey2 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedAfterEachCallbackKey2 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedExecutionConditionKey3 = executionConditionKey(nestedTestClass, testsInvoked.get(2)); String nestedBeforeEachCallbackKey3 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(2)); String nestedAfterEachCallbackKey3 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(2)); // @formatter:off assertThat(instanceMap.keySet()).containsExactlyInAnyOrder( containerExecutionConditionKey, nestedTestTemplateKey, nestedContainerExecutionConditionKey, postProcessTestInstanceKey, nestedPostProcessTestInstanceKey, preDestroyCallbackTestInstanceKey, nestedPreDestroyCallbackTestInstanceKey, beforeAllCallbackKey, afterAllCallbackKey, outerTestExecutionConditionKey, beforeEachCallbackKey, afterEachCallbackKey, nestedBeforeAllCallbackKey, nestedAfterAllCallbackKey, nestedExecutionConditionKey1, nestedBeforeEachCallbackKey1, nestedAfterEachCallbackKey1, nestedExecutionConditionKey2, nestedBeforeEachCallbackKey2, nestedAfterEachCallbackKey2, nestedExecutionConditionKey3, nestedBeforeEachCallbackKey3, nestedAfterEachCallbackKey3 ); // @formatter:on assertNull(instanceMap.get(containerExecutionConditionKey)); assertNull(instanceMap.get(beforeAllCallbackKey)); assertNull(instanceMap.get(afterAllCallbackKey)); assertNull(instanceMap.get(nestedContainerExecutionConditionKey)); assertNull(instanceMap.get(nestedBeforeAllCallbackKey)); assertNull(instanceMap.get(nestedAfterAllCallbackKey)); TestInstances outerInstances = instanceMap.get(beforeEachCallbackKey); assertNotNull(outerInstances.getInnermostInstance()); assertSame(outerInstances, instanceMap.get(afterEachCallbackKey)); assertSame(outerInstances, instanceMap.get(outerTestExecutionConditionKey)); TestInstances nestedInstances1 = instanceMap.get(nestedBeforeEachCallbackKey1); assertNotNull(nestedInstances1.getInnermostInstance()); assertNotSame(outerInstances.getInnermostInstance(), nestedInstances1.getInnermostInstance()); assertSame(nestedInstances1, instanceMap.get(nestedAfterEachCallbackKey1)); assertSame(nestedInstances1, instanceMap.get(nestedExecutionConditionKey1)); TestInstances nestedInstances2 = instanceMap.get(nestedBeforeEachCallbackKey2); assertNotNull(nestedInstances2.getInnermostInstance()); assertNotSame(outerInstances.getInnermostInstance(), nestedInstances2.getInnermostInstance()); assertNotSame(nestedInstances1.getInnermostInstance(), nestedInstances2.getInnermostInstance()); assertSame(nestedInstances2, instanceMap.get(nestedAfterEachCallbackKey2)); assertSame(nestedInstances2, instanceMap.get(nestedExecutionConditionKey2)); TestInstances nestedInstances3 = instanceMap.get(nestedPostProcessTestInstanceKey); assertNotNull(nestedInstances3.getInnermostInstance()); assertNotSame(outerInstances.getInnermostInstance(), nestedInstances3.getInnermostInstance()); assertNotSame(nestedInstances1.getInnermostInstance(), nestedInstances3.getInnermostInstance()); assertSame(nestedInstances3.getInnermostInstance(), instanceMap.get(nestedAfterEachCallbackKey3).getInnermostInstance()); assertSame(nestedInstances3.getInnermostInstance(), instanceMap.get(nestedExecutionConditionKey3).getInnermostInstance()); assertSame(nestedInstances3.getInnermostInstance(), instanceMap.get(nestedPreDestroyCallbackTestInstanceKey).getInnermostInstance()); Object outerInstance1 = instanceMap.get(nestedExecutionConditionKey1).findInstance(testClass).get(); Object outerInstance2 = instanceMap.get(nestedExecutionConditionKey2).findInstance(testClass).get(); Object outerInstance3 = instanceMap.get(nestedExecutionConditionKey3).findInstance(testClass).get(); assertNotSame(outerInstance1, outerInstance2); assertNotSame(outerInstance1, outerInstance3); assertThat(instanceMap.get(nestedExecutionConditionKey1).getAllInstances()).containsExactly(outerInstance1, nestedInstances1.getInnermostInstance()); assertThat(instanceMap.get(nestedExecutionConditionKey2).getAllInstances()).containsExactly(outerInstance2, nestedInstances2.getInnermostInstance()); assertThat(instanceMap.get(nestedExecutionConditionKey3).getAllInstances()).containsExactly(outerInstance3, nestedInstances3.getInnermostInstance()); // The last tracked instance stored under postProcessTestInstanceKey // is only created in order to instantiate the nested test class for // test2(). assertSame(outerInstance3, instanceMap.get(postProcessTestInstanceKey).getInnermostInstance()); assertThat(lifecyclesMap.keySet()).containsExactly(testClass, nestedTestClass); assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_METHOD::equals); assertThat(lifecyclesMap.get(nestedTestClass).stream()).allMatch(Lifecycle.PER_METHOD::equals); } @Test void instancePerClassWithNestedTestClass() { Class testClass = InstancePerClassOuterTestCase.class; Class nestedTestClass = InstancePerClassOuterTestCase.NestedInstancePerClassTestCase.class; int containers = 4; int tests = 4; Map.Entry, Integer>[] instances = instanceCounts(entry(testClass, 1), entry(nestedTestClass, 1)); int allMethods = 2; int eachMethods = 3; performAssertions(testClass, containers, tests, instances, allMethods, eachMethods); String containerExecutionConditionKey = executionConditionKey(testClass, null); String nestedContainerExecutionConditionKey = executionConditionKey(nestedTestClass, null); String nestedTestTemplateKey = testTemplateKey(nestedTestClass, "singletonTest"); String postProcessTestInstanceKey = postProcessTestInstanceKey(testClass); String nestedPostProcessTestInstanceKey = postProcessTestInstanceKey(nestedTestClass); String preDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(testClass); String nestedPreDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(nestedTestClass); String beforeAllCallbackKey = beforeAllCallbackKey(testClass); String afterAllCallbackKey = afterAllCallbackKey(testClass); String outerTestExecutionConditionKey = executionConditionKey(testClass, "outerTest"); String beforeEachCallbackKey = beforeEachCallbackKey(testClass, "outerTest"); String afterEachCallbackKey = afterEachCallbackKey(testClass, "outerTest"); String nestedBeforeAllCallbackKey = beforeAllCallbackKey(nestedTestClass); String nestedAfterAllCallbackKey = afterAllCallbackKey(nestedTestClass); String nestedExecutionConditionKey1 = executionConditionKey(nestedTestClass, testsInvoked.get(0)); String nestedBeforeEachCallbackKey1 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedAfterEachCallbackKey1 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedExecutionConditionKey2 = executionConditionKey(nestedTestClass, testsInvoked.get(1)); String nestedBeforeEachCallbackKey2 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedAfterEachCallbackKey2 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedExecutionConditionKey3 = executionConditionKey(nestedTestClass, testsInvoked.get(2)); String nestedBeforeEachCallbackKey3 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(2)); String nestedAfterEachCallbackKey3 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(2)); // @formatter:off assertThat(instanceMap.keySet()).containsExactlyInAnyOrder( containerExecutionConditionKey, nestedTestTemplateKey, nestedContainerExecutionConditionKey, postProcessTestInstanceKey, nestedPostProcessTestInstanceKey, preDestroyCallbackTestInstanceKey, nestedPreDestroyCallbackTestInstanceKey, beforeAllCallbackKey, afterAllCallbackKey, outerTestExecutionConditionKey, beforeEachCallbackKey, afterEachCallbackKey, nestedBeforeAllCallbackKey, nestedAfterAllCallbackKey, nestedExecutionConditionKey1, nestedBeforeEachCallbackKey1, nestedAfterEachCallbackKey1, nestedExecutionConditionKey2, nestedBeforeEachCallbackKey2, nestedAfterEachCallbackKey2, nestedExecutionConditionKey3, nestedBeforeEachCallbackKey3, nestedAfterEachCallbackKey3 ); // @formatter:on Object instance = instanceMap.get(postProcessTestInstanceKey).getInnermostInstance(); assertNotNull(instance); assertNull(instanceMap.get(containerExecutionConditionKey)); assertSame(instance, instanceMap.get(beforeAllCallbackKey).getInnermostInstance()); assertSame(instance, instanceMap.get(afterAllCallbackKey).getInnermostInstance()); assertSame(instance, instanceMap.get(outerTestExecutionConditionKey).getInnermostInstance()); assertSame(instance, instanceMap.get(beforeEachCallbackKey).getInnermostInstance()); assertSame(instance, instanceMap.get(afterEachCallbackKey).getInnermostInstance()); assertSame(instance, instanceMap.get(preDestroyCallbackTestInstanceKey).getInnermostInstance()); Object nestedInstance = instanceMap.get(nestedPostProcessTestInstanceKey).getInnermostInstance(); assertNotNull(nestedInstance); assertNotSame(instance, nestedInstance); assertNull(instanceMap.get(nestedContainerExecutionConditionKey)); assertSame(nestedInstance, instanceMap.get(nestedBeforeAllCallbackKey).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterAllCallbackKey).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedPreDestroyCallbackTestInstanceKey).getInnermostInstance()); Object outerInstance = instanceMap.get(nestedExecutionConditionKey1).findInstance(testClass).get(); assertSame(outerInstance, instance); assertSame(outerInstance, instanceMap.get(postProcessTestInstanceKey).getInnermostInstance()); assertSame(outerInstance, instanceMap.get(preDestroyCallbackTestInstanceKey).getInnermostInstance()); assertThat(instanceMap.get(nestedExecutionConditionKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedExecutionConditionKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedExecutionConditionKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(lifecyclesMap.keySet()).containsExactly(testClass, nestedTestClass); assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); assertThat(lifecyclesMap.get(nestedTestClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); } @Test void instancePerMethodOnOuterTestClassWithInstancePerClassOnNestedTestClass() { Class testClass = MixedLifecyclesOuterTestCase.class; Class nestedTestClass = MixedLifecyclesOuterTestCase.NestedInstancePerClassTestCase.class; int containers = 4; int tests = 4; Map.Entry, Integer>[] instances = instanceCounts(entry(testClass, 2), entry(nestedTestClass, 1)); int allMethods = 1; int eachMethods = 7; performAssertions(testClass, containers, tests, instances, allMethods, eachMethods); String containerExecutionConditionKey = executionConditionKey(testClass, null); String nestedContainerExecutionConditionKey = executionConditionKey(nestedTestClass, null); String nestedTestTemplateKey = testTemplateKey(nestedTestClass, "singletonTest"); String postProcessTestInstanceKey = postProcessTestInstanceKey(testClass); String nestedPostProcessTestInstanceKey = postProcessTestInstanceKey(nestedTestClass); String preDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(testClass); String nestedPreDestroyCallbackTestInstanceKey = preDestroyCallbackTestInstanceKey(nestedTestClass); String beforeAllCallbackKey = beforeAllCallbackKey(testClass); String afterAllCallbackKey = afterAllCallbackKey(testClass); String outerTestExecutionConditionKey = executionConditionKey(testClass, "outerTest"); String beforeEachCallbackKey = beforeEachCallbackKey(testClass, "outerTest"); String afterEachCallbackKey = afterEachCallbackKey(testClass, "outerTest"); String nestedBeforeAllCallbackKey = beforeAllCallbackKey(nestedTestClass); String nestedAfterAllCallbackKey = afterAllCallbackKey(nestedTestClass); String nestedExecutionConditionKey1 = executionConditionKey(nestedTestClass, testsInvoked.get(0)); String nestedBeforeEachCallbackKey1 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedAfterEachCallbackKey1 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(0)); String nestedExecutionConditionKey2 = executionConditionKey(nestedTestClass, testsInvoked.get(1)); String nestedBeforeEachCallbackKey2 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedAfterEachCallbackKey2 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(1)); String nestedExecutionConditionKey3 = executionConditionKey(nestedTestClass, testsInvoked.get(2)); String nestedBeforeEachCallbackKey3 = beforeEachCallbackKey(nestedTestClass, testsInvoked.get(2)); String nestedAfterEachCallbackKey3 = afterEachCallbackKey(nestedTestClass, testsInvoked.get(2)); // @formatter:off assertThat(instanceMap.keySet()).containsExactlyInAnyOrder( containerExecutionConditionKey, nestedTestTemplateKey, nestedContainerExecutionConditionKey, postProcessTestInstanceKey, nestedPostProcessTestInstanceKey, preDestroyCallbackTestInstanceKey, nestedPreDestroyCallbackTestInstanceKey, beforeAllCallbackKey, afterAllCallbackKey, outerTestExecutionConditionKey, beforeEachCallbackKey, afterEachCallbackKey, nestedBeforeAllCallbackKey, nestedAfterAllCallbackKey, nestedExecutionConditionKey1, nestedBeforeEachCallbackKey1, nestedAfterEachCallbackKey1, nestedExecutionConditionKey2, nestedBeforeEachCallbackKey2, nestedAfterEachCallbackKey2, nestedExecutionConditionKey3, nestedBeforeEachCallbackKey3, nestedAfterEachCallbackKey3 ); // @formatter:on assertNull(instanceMap.get(containerExecutionConditionKey)); assertNull(instanceMap.get(beforeAllCallbackKey)); assertNull(instanceMap.get(afterAllCallbackKey)); TestInstances outerInstances = instanceMap.get(beforeEachCallbackKey); assertSame(outerInstances, instanceMap.get(afterEachCallbackKey)); assertSame(outerInstances, instanceMap.get(outerTestExecutionConditionKey)); Object nestedInstance = instanceMap.get(nestedPostProcessTestInstanceKey).getInnermostInstance(); assertNotNull(nestedInstance); assertNotSame(outerInstances.getInnermostInstance(), nestedInstance); assertNull(instanceMap.get(nestedContainerExecutionConditionKey)); assertSame(nestedInstance, instanceMap.get(nestedBeforeAllCallbackKey).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterAllCallbackKey).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey1).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey2).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedExecutionConditionKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedBeforeEachCallbackKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedAfterEachCallbackKey3).getInnermostInstance()); assertSame(nestedInstance, instanceMap.get(nestedPreDestroyCallbackTestInstanceKey).getInnermostInstance()); // The last tracked instance stored under postProcessTestInstanceKey // is only created in order to instantiate the nested test class. Object outerInstance = instanceMap.get(nestedExecutionConditionKey1).findInstance(testClass).get(); assertEquals(outerInstances.getInnermostInstance().getClass(), outerInstance.getClass()); assertNotSame(outerInstances.getInnermostInstance(), outerInstance); assertThat(instanceMap.get(nestedExecutionConditionKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey1).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedExecutionConditionKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey2).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedExecutionConditionKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedBeforeEachCallbackKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(instanceMap.get(nestedAfterEachCallbackKey3).getAllInstances()).containsExactly(outerInstance, nestedInstance); assertThat(lifecyclesMap.keySet()).containsExactly(testClass, nestedTestClass); assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_METHOD::equals); assertThat(lifecyclesMap.get(nestedTestClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); } private void performAssertions(Class testClass, int numContainers, int numTests, Map.Entry, Integer>[] instanceCountEntries, int allMethods, int eachMethods) { EngineExecutionResults executionResults = executeTestsForClass(testClass); executionResults.containerEvents().assertStatistics( stats -> stats.started(numContainers).finished(numContainers)); executionResults.testEvents().assertStatistics(stats -> stats.started(numTests).finished(numTests)); // @formatter:off assertAll( () -> assertThat(instanceCount).describedAs("instance count").contains(instanceCountEntries), () -> assertEquals(allMethods, beforeAllCount, "@BeforeAll count"), () -> assertEquals(allMethods, afterAllCount, "@AfterAll count"), () -> assertEquals(eachMethods, beforeEachCount, "@BeforeEach count"), () -> assertEquals(eachMethods, afterEachCount, "@AfterEach count") ); // @formatter:on } @SafeVarargs @SuppressWarnings("varargs") private final Map.Entry, Integer>[] instanceCounts(Map.Entry, Integer>... entries) { return entries; } private static void incrementInstanceCount(Class testClass) { instanceCount.compute(testClass, (key, value) -> value == null ? 1 : value + 1); } private static String executionConditionKey(Class testClass, String testMethod) { return concat(ExecutionCondition.class, testClass, testMethod); } private static String postProcessTestInstanceKey(Class testClass) { return concat(TestInstancePostProcessor.class, testClass); } private static String preDestroyCallbackTestInstanceKey(Class testClass) { return concat(TestInstancePreDestroyCallback.class, testClass); } private static String beforeAllCallbackKey(Class testClass) { return concat(BeforeAllCallback.class, testClass); } private static String afterAllCallbackKey(Class testClass) { return concat(AfterAllCallback.class, testClass); } private static String beforeEachCallbackKey(Class testClass, String testMethod) { return concat(BeforeEachCallback.class, testClass, testMethod); } private static String afterEachCallbackKey(Class testClass, String testMethod) { return concat(AfterEachCallback.class, testClass, testMethod); } private static String testTemplateKey(Class testClass, String testMethod) { return concat(TestTemplateInvocationContextProvider.class, testClass, testMethod); } private static String concat(Class c1, Class c2, String str) { return concat(c1.getSimpleName(), c2.getSimpleName(), str); } private static String concat(Class c1, Class c2) { return concat(c1.getSimpleName(), c2.getSimpleName()); } private static String concat(String... args) { return join(".", args); } // ------------------------------------------------------------------------- @ExtendWith(InstanceTrackingExtension.class) // The following is commented out b/c it's the default. // @TestInstance(Lifecycle.PER_METHOD) static class InstancePerMethodTestCase { InstancePerMethodTestCase() { incrementInstanceCount(InstancePerMethodTestCase.class); } @BeforeAll static void beforeAllStatic(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @BeforeEach void beforeEach() { beforeEachCount++; } @Test void test1(TestInfo testInfo) { testsInvoked.add(testInfo.getTestMethod().get().getName()); } @Test void test2(TestInfo testInfo) { testsInvoked.add(testInfo.getTestMethod().get().getName()); } @SingletonTest void singletonTest(TestInfo testInfo) { testsInvoked.add(testInfo.getTestMethod().get().getName()); } @AfterEach void afterEach() { afterEachCount++; } @AfterAll static void afterAllStatic(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } } @TestInstance(Lifecycle.PER_CLASS) static class InstancePerClassTestCase extends InstancePerMethodTestCase { InstancePerClassTestCase() { incrementInstanceCount(InstancePerClassTestCase.class); } @BeforeAll void beforeAll(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @AfterAll void afterAll(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } } static class SubInstancePerClassTestCase extends InstancePerClassTestCase { SubInstancePerClassTestCase() { incrementInstanceCount(SubInstancePerClassTestCase.class); } } @ExtendWith(InstanceTrackingExtension.class) // The following is commented out b/c it's the default. // @TestInstance(Lifecycle.PER_METHOD) static class InstancePerMethodOuterTestCase { InstancePerMethodOuterTestCase() { incrementInstanceCount(InstancePerMethodOuterTestCase.class); } @BeforeAll static void beforeAll(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); } @AfterAll static void afterAll(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } @Nested // The following is commented out b/c it's the default. // @TestInstance(Lifecycle.PER_METHOD) class NestedInstancePerMethodTestCase { NestedInstancePerMethodTestCase() { incrementInstanceCount(NestedInstancePerMethodTestCase.class); } @BeforeEach void beforeEach() { beforeEachCount++; } @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @AfterEach void afterEach() { afterEachCount++; } } } @ExtendWith(InstanceTrackingExtension.class) @TestInstance(Lifecycle.PER_CLASS) static class InstancePerClassOuterTestCase { InstancePerClassOuterTestCase() { incrementInstanceCount(InstancePerClassOuterTestCase.class); } @BeforeAll static void beforeAll(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); } @AfterAll static void afterAll(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } @Nested @TestInstance(Lifecycle.PER_CLASS) class NestedInstancePerClassTestCase { NestedInstancePerClassTestCase() { incrementInstanceCount(NestedInstancePerClassTestCase.class); } @BeforeAll void beforeAll(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @BeforeEach void beforeEach() { beforeEachCount++; } @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @AfterEach void afterEach() { afterEachCount++; } @AfterAll void afterAll(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } } } @ExtendWith(InstanceTrackingExtension.class) // The following is commented out b/c it's the default. // @TestInstance(Lifecycle.PER_METHOD) static class MixedLifecyclesOuterTestCase { MixedLifecyclesOuterTestCase() { incrementInstanceCount(MixedLifecyclesOuterTestCase.class); } @BeforeEach void beforeEach() { beforeEachCount++; } @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); } @AfterEach void afterEach() { afterEachCount++; } @Nested @TestInstance(Lifecycle.PER_CLASS) class NestedInstancePerClassTestCase { NestedInstancePerClassTestCase() { incrementInstanceCount(NestedInstancePerClassTestCase.class); } @BeforeAll void beforeAll(TestInfo testInfo) { assertNotNull(testInfo); beforeAllCount++; } @BeforeEach void beforeEach() { beforeEachCount++; } @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } @AfterEach void afterEach() { afterEachCount++; } @AfterAll void afterAll(TestInfo testInfo) { assertNotNull(testInfo); afterAllCount++; } } } // Intentionally not implementing BeforeTestExecutionCallback, AfterTestExecutionCallback, // and TestExecutionExceptionHandler, since they are analogous to BeforeEachCallback and // AfterEachCallback with regard to instance scope and Lifecycle. static class InstanceTrackingExtension implements ExecutionCondition, TestInstancePostProcessor, TestInstancePreDestroyCallback, BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, TestTemplateInvocationContextProvider { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { trackLifecycle(context); String testMethod = context.getTestMethod().map(Method::getName).orElse(null); if (testMethod == null) { assertThat(context.getTestInstance()).isNotPresent(); assertThat(instanceCount.getOrDefault(context.getRequiredTestClass(), 0)).isEqualTo(0); } instanceMap.put(executionConditionKey(context.getRequiredTestClass(), testMethod), context.getTestInstances().orElse(null)); return ConditionEvaluationResult.enabled("enigma"); } @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { trackLifecycle(context); assertThat(context.getTestInstance()).isNotPresent(); assertNotNull(testInstance); instanceMap.put(postProcessTestInstanceKey(context.getRequiredTestClass()), DefaultTestInstances.of(testInstance)); } @Override public void preDestroyTestInstance(ExtensionContext context) { trackLifecycle(context); assertThat(context.getTestInstance()).isPresent(); instanceMap.put(preDestroyCallbackTestInstanceKey(context.getRequiredTestClass()), DefaultTestInstances.of(context.getTestInstance().get())); } @Override public void beforeAll(ExtensionContext context) { trackLifecycle(context); instanceMap.put(beforeAllCallbackKey(context.getRequiredTestClass()), context.getTestInstances().orElse(null)); } @Override public void afterAll(ExtensionContext context) { trackLifecycle(context); instanceMap.put(afterAllCallbackKey(context.getRequiredTestClass()), context.getTestInstances().orElse(null)); } @Override public void beforeEach(ExtensionContext context) { trackLifecycle(context); instanceMap.put( beforeEachCallbackKey(context.getRequiredTestClass(), context.getRequiredTestMethod().getName()), context.getRequiredTestInstances()); } @Override public void afterEach(ExtensionContext context) { trackLifecycle(context); instanceMap.put( afterEachCallbackKey(context.getRequiredTestClass(), context.getRequiredTestMethod().getName()), context.getRequiredTestInstances()); } @Override public boolean supportsTestTemplate(ExtensionContext context) { trackLifecycle(context); return isAnnotated(context.getTestMethod(), SingletonTest.class); } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { trackLifecycle(context); instanceMap.put(testTemplateKey(context.getRequiredTestClass(), context.getRequiredTestMethod().getName()), context.getTestInstances().orElse(null)); return Stream.of(new TestTemplateInvocationContext() { }); } private static void trackLifecycle(ExtensionContext context) { assertThat(context.getRoot().getTestInstanceLifecycle()).isEmpty(); lifecyclesMap.computeIfAbsent(context.getRequiredTestClass(), clazz -> new ArrayList<>()).add( context.getTestInstanceLifecycle().orElse(null)); } } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @TestTemplate @interface SingletonTest { } } TestTemplateInvocationTests.java000066400000000000000000000745471455764576500351360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.dynamicTestRegistered; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; import java.util.stream.Stream; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Event; import org.junit.platform.testkit.engine.Events; import org.opentest4j.AssertionFailedError; /** * @since 5.0 */ class TestTemplateInvocationTests extends AbstractJupiterTestEngineTests { @Test void templateWithSingleRegisteredExtensionIsInvoked() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithSingleRegisteredExtension")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithSingleRegisteredExtension"), started()), // event(dynamicTestRegistered("test-template-invocation:#1")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("invocation is expected to fail"))), // event(container("templateWithSingleRegisteredExtension"), finishedSuccessfully()))); } @Test void parentRelationshipIsEstablished() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithSingleRegisteredExtension")).build(); EngineExecutionResults executionResults = executeTests(request); TestDescriptor templateMethodDescriptor = findTestDescriptor(executionResults, container("templateWithSingleRegisteredExtension")); TestDescriptor invocationDescriptor = findTestDescriptor(executionResults, test("test-template-invocation:#1")); assertThat(invocationDescriptor.getParent()).hasValue(templateMethodDescriptor); } @Test void beforeAndAfterEachMethodsAreExecutedAroundInvocation() { LauncherDiscoveryRequest request = request().selectors( selectMethod(TestTemplateTestClassWithBeforeAndAfterEach.class, "testTemplateWithTwoInvocations")).build(); executeTests(request); assertThat(TestTemplateTestClassWithBeforeAndAfterEach.lifecycleEvents).containsExactly( "beforeAll:TestTemplateInvocationTests$TestTemplateTestClassWithBeforeAndAfterEach", "beforeEach:[1]", "afterEach:[1]", "beforeEach:[2]", "afterEach:[2]", "afterAll:TestTemplateInvocationTests$TestTemplateTestClassWithBeforeAndAfterEach"); } @Test void templateWithTwoRegisteredExtensionsIsInvoked() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithTwoRegisteredExtensions")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithTwoRegisteredExtensions"), started()), // event(dynamicTestRegistered("test-template-invocation:#1"), displayName("[1]")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("invocation is expected to fail"))), // event(dynamicTestRegistered("test-template-invocation:#2"), displayName("[2]")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedWithFailure(message("invocation is expected to fail"))), // event(container("templateWithTwoRegisteredExtensions"), finishedSuccessfully()))); } @Test void legacyReportingNames() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithTwoRegisteredExtensions")).build(); EngineExecutionResults results = executeTests(request); Events events = results.allEvents(); events.assertStatistics(stats -> stats.dynamicallyRegistered(2)); // events.dynamicallyRegistered().debug(); // results.testEvents().dynamicallyRegistered().debug(); // results.containerEvents().dynamicallyRegistered().debug(); // @formatter:off Stream legacyReportingNames = events.dynamicallyRegistered() .map(Event::getTestDescriptor) .map(TestDescriptor::getLegacyReportingName); // @formatter:off assertThat(legacyReportingNames).containsExactly("templateWithTwoRegisteredExtensions()[1]", "templateWithTwoRegisteredExtensions()[2]"); } @Test void templateWithTwoInvocationsFromSingleExtensionIsInvoked() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithTwoInvocationsFromSingleExtension")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithTwoInvocationsFromSingleExtension"), started()), // event(dynamicTestRegistered("test-template-invocation:#1"), displayName("[1]")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("invocation is expected to fail"))), // event(dynamicTestRegistered("test-template-invocation:#2"), displayName("[2]")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedWithFailure(message("invocation is expected to fail"))), // event(container("templateWithTwoInvocationsFromSingleExtension"), finishedSuccessfully()))); } @Test void singleInvocationIsExecutedWhenDiscoveredByUniqueId() { UniqueId uniqueId = discoverUniqueId(MyTestTemplateTestCase.class, "templateWithTwoInvocationsFromSingleExtension") // .append(TestTemplateInvocationTestDescriptor.SEGMENT_TYPE, "#2"); EngineExecutionResults executionResults = executeTests(selectUniqueId(uniqueId)); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithTwoInvocationsFromSingleExtension"), started()), // event(dynamicTestRegistered("test-template-invocation:#2"), displayName("[2]")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedWithFailure(message("invocation is expected to fail"))), // event(container("templateWithTwoInvocationsFromSingleExtension"), finishedSuccessfully()))); } @Test void templateWithDisabledInvocationsIsSkipped() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithDisabledInvocations")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithDisabledInvocations"), started()), // event(dynamicTestRegistered("test-template-invocation:#1")), // event(test("test-template-invocation:#1"), skippedWithReason("always disabled")), // event(container("templateWithDisabledInvocations"), finishedSuccessfully()))); } @Test void disabledTemplateIsSkipped() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "disabledTemplate")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("disabledTemplate"), skippedWithReason("always disabled")))); } @Test void templateWithCustomizedDisplayNamesIsInvoked() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithCustomizedDisplayNames")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithCustomizedDisplayNames"), started()), // event(dynamicTestRegistered("test-template-invocation:#1"), displayName("1 --> templateWithCustomizedDisplayNames()")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("invocation is expected to fail"))), // event(container("templateWithCustomizedDisplayNames"), finishedSuccessfully()))); } @Test void templateWithDynamicParameterResolverIsInvoked() { LauncherDiscoveryRequest request = request().selectors(selectMethod(MyTestTemplateTestCase.class, "templateWithDynamicParameterResolver", "java.lang.String")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithDynamicParameterResolver"), started()), // event(dynamicTestRegistered("test-template-invocation:#1"), displayName("[1] foo")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("foo"))), // event(dynamicTestRegistered("test-template-invocation:#2"), displayName("[2] bar")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedWithFailure(message("bar"))), // event(container("templateWithDynamicParameterResolver"), finishedSuccessfully()))); } @Test void contextParameterResolverCanResolveConstructorArguments() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCaseWithConstructor.class, "template", "java.lang.String")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("template"), started()), // event(dynamicTestRegistered("test-template-invocation:#1"), displayName("[1] foo")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedSuccessfully()), // event(dynamicTestRegistered("test-template-invocation:#2"), displayName("[2] bar")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedSuccessfully()), // event(container("template"), finishedSuccessfully()))); } @Test void templateWithDynamicTestInstancePostProcessorIsInvoked() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithDynamicTestInstancePostProcessor")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithDynamicTestInstancePostProcessor"), started()), // event(dynamicTestRegistered("test-template-invocation:#1")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedWithFailure(message("foo"))), // event(dynamicTestRegistered("test-template-invocation:#2")), // event(test("test-template-invocation:#2"), started()), // event(test("test-template-invocation:#2"), finishedWithFailure(message("bar"))), // event(container("templateWithDynamicTestInstancePostProcessor"), finishedSuccessfully()))); } @Test void lifecycleCallbacksAreExecutedForInvocation() { LauncherDiscoveryRequest request = request().selectors( selectClass(TestTemplateTestClassWithDynamicLifecycleCallbacks.class)).build(); executeTests(request); // @formatter:off assertThat(TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents).containsExactly( "beforeEach", "beforeTestExecution", "testTemplate:foo", "handleTestExecutionException", "afterTestExecution", "afterEach", "beforeEach", "beforeTestExecution", "testTemplate:bar", "afterTestExecution", "afterEach"); // @formatter:on } @Test void extensionIsAskedForSupportBeforeItMustProvide() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithWrongParameterType", int.class.getName())).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithWrongParameterType"), started()), // event(container("templateWithWrongParameterType"), finishedWithFailure(message(s -> s.startsWith( "You must register at least one TestTemplateInvocationContextProvider that supports @TestTemplate method [")))))); } @Test void templateWithSupportingProviderButNoInvocationsReportsFailure() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithSupportingProviderButNoInvocations")).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithSupportingProviderButNoInvocations"), started()), // event(container("templateWithSupportingProviderButNoInvocations"), finishedWithFailure(message("None of the supporting TestTemplateInvocationContextProviders [" + InvocationContextProviderThatSupportsEverythingButProvidesNothing.class.getSimpleName() + "] provided a non-empty stream"))))); } @Test void templateWithCloseableStream() { LauncherDiscoveryRequest request = request().selectors( selectMethod(MyTestTemplateTestCase.class, "templateWithCloseableStream")).build(); EngineExecutionResults executionResults = executeTests(request); assertThat(InvocationContextProviderWithCloseableStream.streamClosed.get()).describedAs( "streamClosed").isTrue(); executionResults.allEvents().assertEventsMatchExactly( // wrappedInContainerEvents(MyTestTemplateTestCase.class, // event(container("templateWithCloseableStream"), started()), // event(dynamicTestRegistered("test-template-invocation:#1")), // event(test("test-template-invocation:#1"), started()), // event(test("test-template-invocation:#1"), finishedSuccessfully()), // event(container("templateWithCloseableStream"), finishedSuccessfully()))); } private TestDescriptor findTestDescriptor(EngineExecutionResults executionResults, Condition condition) { // @formatter:off return executionResults.allEvents() .filter(condition::matches) .findAny() .map(Event::getTestDescriptor) .orElseThrow(() -> new AssertionFailedError("Could not find event for condition: " + condition)); // @formatter:on } @SafeVarargs @SuppressWarnings({ "unchecked", "varargs", "rawtypes" }) private final Condition[] wrappedInContainerEvents(Class clazz, Condition... wrappedConditions) { List> conditions = new ArrayList<>(); conditions.add(event(engine(), started())); conditions.add(event(container(clazz), started())); conditions.addAll(asList(wrappedConditions)); conditions.add(event(container(clazz), finishedSuccessfully())); conditions.add(event(engine(), finishedSuccessfully())); return conditions.toArray(new Condition[0]); } static class MyTestTemplateTestCase { @TestTemplate void templateWithoutRegisteredExtension() { } @ExtendWith(SingleInvocationContextProvider.class) @TestTemplate void templateWithSingleRegisteredExtension() { fail("invocation is expected to fail"); } @ExtendWith({ SingleInvocationContextProvider.class, AnotherInvocationContextProviderWithASingleInvocation.class }) @TestTemplate void templateWithTwoRegisteredExtensions() { fail("invocation is expected to fail"); } @ExtendWith(TwoInvocationsContextProvider.class) @TestTemplate void templateWithTwoInvocationsFromSingleExtension() { fail("invocation is expected to fail"); } @ExtendWith({ SingleInvocationContextProviderWithDisabledInvocations.class }) @TestTemplate void templateWithDisabledInvocations() { fail("this is never called"); } @ExtendWith(AlwaysDisabledExecutionCondition.class) @TestTemplate void disabledTemplate() { fail("this is never called"); } @ExtendWith(InvocationContextProviderWithCustomizedDisplayNames.class) @TestTemplate void templateWithCustomizedDisplayNames() { fail("invocation is expected to fail"); } @ExtendWith(StringParameterResolvingInvocationContextProvider.class) @TestTemplate void templateWithDynamicParameterResolver(String parameter) { fail(parameter); } @ExtendWith(StringParameterResolvingInvocationContextProvider.class) @TestTemplate void templateWithWrongParameterType(int parameter) { fail("never called: " + parameter); } String parameterInstanceVariable; @ExtendWith(StringParameterInjectingInvocationContextProvider.class) @TestTemplate void templateWithDynamicTestInstancePostProcessor() { fail(parameterInstanceVariable); } @ExtendWith(InvocationContextProviderThatSupportsEverythingButProvidesNothing.class) @TestTemplate void templateWithSupportingProviderButNoInvocations() { fail("never called"); } @ExtendWith(InvocationContextProviderWithCloseableStream.class) @TestTemplate void templateWithCloseableStream() { } } @ExtendWith(StringParameterResolvingInvocationContextProvider.class) static class MyTestTemplateTestCaseWithConstructor { private final String constructorParameter; MyTestTemplateTestCaseWithConstructor(String constructorParameter) { this.constructorParameter = constructorParameter; } @TestTemplate void template(String parameter) { assertEquals(constructorParameter, parameter); } } static class TestTemplateTestClassWithBeforeAndAfterEach { private static List lifecycleEvents = new ArrayList<>(); @BeforeAll static void beforeAll(TestInfo testInfo) { lifecycleEvents.add("beforeAll:" + testInfo.getDisplayName()); } @AfterAll static void afterAll(TestInfo testInfo) { lifecycleEvents.add("afterAll:" + testInfo.getDisplayName()); } @BeforeEach void beforeEach(TestInfo testInfo) { lifecycleEvents.add("beforeEach:" + testInfo.getDisplayName()); } @AfterEach void afterEach(TestInfo testInfo) { lifecycleEvents.add("afterEach:" + testInfo.getDisplayName()); } @ExtendWith(TwoInvocationsContextProvider.class) @TestTemplate void testTemplateWithTwoInvocations() { fail("invocation is expected to fail"); } } static class TestTemplateTestClassWithDynamicLifecycleCallbacks { private static List lifecycleEvents = new ArrayList<>(); @ExtendWith(InvocationContextProviderWithDynamicLifecycleCallbacks.class) @TestTemplate void testTemplate(TestInfo testInfo) { lifecycleEvents.add("testTemplate:" + testInfo.getDisplayName()); assertEquals("bar", testInfo.getDisplayName()); } } private static class SingleInvocationContextProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(emptyTestTemplateInvocationContext()); } } private static class SingleInvocationContextProviderWithDisabledInvocations extends SingleInvocationContextProvider { @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(new TestTemplateInvocationContext() { @Override public List getAdditionalExtensions() { return singletonList(new AlwaysDisabledExecutionCondition()); } }); } } private static class AnotherInvocationContextProviderWithASingleInvocation implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(emptyTestTemplateInvocationContext()); } } private static class TwoInvocationsContextProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(emptyTestTemplateInvocationContext(), emptyTestTemplateInvocationContext()); } } private static class AlwaysDisabledExecutionCondition implements ExecutionCondition { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return ConditionEvaluationResult.disabled("always disabled"); } } private static class InvocationContextProviderWithCustomizedDisplayNames implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream. generate(() -> new TestTemplateInvocationContext() { @Override public String getDisplayName(int invocationIndex) { return invocationIndex + " --> " + context.getDisplayName(); } }).limit(1); } } private static class StringParameterResolvingInvocationContextProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { // @formatter:off return context.getTestMethod() .map(Method::getParameterTypes) .map(Arrays::stream) .map(parameters -> parameters.anyMatch(Predicate.isEqual(String.class))) .orElse(false); // @formatter:on } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(createContext("foo"), createContext("bar")); } private TestTemplateInvocationContext createContext(String argument) { return new TestTemplateInvocationContext() { @Override public String getDisplayName(int invocationIndex) { return TestTemplateInvocationContext.super.getDisplayName(invocationIndex) + " " + argument; } @Override public List getAdditionalExtensions() { return singletonList(new ParameterResolver() { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return true; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return argument; } }); } }; } } private static class StringParameterInjectingInvocationContextProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(createContext("foo"), createContext("bar")); } private TestTemplateInvocationContext createContext(String argument) { return new TestTemplateInvocationContext() { @Override public String getDisplayName(int invocationIndex) { return TestTemplateInvocationContext.super.getDisplayName(invocationIndex) + " " + argument; } @Override public List getAdditionalExtensions() { return singletonList((TestInstancePostProcessor) (testInstance, context) -> { Field field = testInstance.getClass().getDeclaredField("parameterInstanceVariable"); field.setAccessible(true); field.set(testInstance, argument); }); } }; } } private static class InvocationContextProviderWithDynamicLifecycleCallbacks implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(createContext("foo"), createContext("bar")); } private TestTemplateInvocationContext createContext(String argument) { return new TestTemplateInvocationContext() { @Override public String getDisplayName(int invocationIndex) { return argument; } @Override public List getAdditionalExtensions() { return singletonList(new LifecycleCallbackExtension()); } }; } private static class LifecycleCallbackExtension implements BeforeEachCallback, BeforeTestExecutionCallback, TestExecutionExceptionHandler, AfterTestExecutionCallback, AfterEachCallback { @Override public void beforeEach(ExtensionContext context) { TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents.add("beforeEach"); } @Override public void beforeTestExecution(ExtensionContext context) { TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents.add("beforeTestExecution"); } @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) { TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents.add("handleTestExecutionException"); throw new AssertionError(throwable); } @Override public void afterTestExecution(ExtensionContext context) { TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents.add("afterTestExecution"); } @Override public void afterEach(ExtensionContext context) { TestTemplateTestClassWithDynamicLifecycleCallbacks.lifecycleEvents.add("afterEach"); } } } private static class InvocationContextProviderThatSupportsEverythingButProvidesNothing implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.empty(); } } private static class InvocationContextProviderWithCloseableStream implements TestTemplateInvocationContextProvider { private static AtomicBoolean streamClosed = new AtomicBoolean(false); @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(emptyTestTemplateInvocationContext()).onClose(() -> streamClosed.set(true)); } } private static TestTemplateInvocationContext emptyTestTemplateInvocationContext() { return new TestTemplateInvocationContext() { }; } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/000077500000000000000000000000001455764576500300755ustar00rootroot00000000000000AbstractNonGenericTests.java000066400000000000000000000024251455764576500354220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; /** * @since 5.0 */ @ExtendWith(NumberResolver.class) abstract class AbstractNonGenericTests { @Test void mA() { BridgeMethodTests.sequence.add("mA()"); } @Test void test(Number value) { BridgeMethodTests.sequence.add("A.test(Number)"); Assertions.assertEquals(42, value); } static class B extends AbstractNonGenericTests { @Test void mB() { BridgeMethodTests.sequence.add("mB()"); } @Test void test(Byte value) { BridgeMethodTests.sequence.add("B.test(Byte)"); Assertions.assertEquals(123, value.intValue()); } } static class C extends B { @Test void mC() { BridgeMethodTests.sequence.add("mC()"); } @Override @Test void test(Byte value) { BridgeMethodTests.sequence.add("C.test(Byte)"); Assertions.assertEquals(123, value.intValue()); } } } AbstractNumberTests.java000066400000000000000000000014721455764576500346240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; /** * @since 5.0 */ @ExtendWith(NumberResolver.class) abstract class AbstractNumberTests { @Test void test(N number) { BridgeMethodTests.sequence.add("test(N)"); assertNotNull(number); assertEquals(123, number.intValue()); } } BridgeMethodTests.java000066400000000000000000000077131455764576500342510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.bridge.NumberTestGroup.ByteTestCase; import org.junit.jupiter.engine.bridge.NumberTestGroup.ShortTestCase; /** * @since 5.0 */ class BridgeMethodTests extends AbstractJupiterTestEngineTests { static List sequence = new ArrayList<>(); @Test void childrenHaveBridgeMethods() throws Exception { assertFalse(ChildWithBridgeMethods.class.getMethod("anotherBeforeEach").isBridge()); assertFalse(ChildWithBridgeMethods.class.getMethod("anotherAfterEach").isBridge()); assertTrue(ChildWithBridgeMethods.class.getMethod("beforeEach").isBridge()); assertTrue(ChildWithBridgeMethods.class.getMethod("afterEach").isBridge()); assertTrue(ByteTestCase.class.getDeclaredMethod("test", Number.class).isBridge()); assertFalse(ByteTestCase.class.getDeclaredMethod("test", Byte.class).isBridge()); assertTrue(ShortTestCase.class.getDeclaredMethod("test", Number.class).isBridge()); assertFalse(ShortTestCase.class.getDeclaredMethod("test", Short.class).isBridge()); } @Test void childHasNoBridgeMethods() throws Exception { assertFalse(ChildWithoutBridgeMethods.class.getMethod("anotherBeforeEach").isBridge()); assertFalse(ChildWithoutBridgeMethods.class.getMethod("anotherAfterEach").isBridge()); assertFalse(ChildWithoutBridgeMethods.class.getMethod("beforeEach").isBridge()); assertFalse(ChildWithoutBridgeMethods.class.getMethod("afterEach").isBridge()); } @Test void compareMethodExecutionSequenceOrder() { String withoutBridgeMethods = execute(1, ChildWithoutBridgeMethods.class); String withBridgeMethods = execute(1, ChildWithBridgeMethods.class); assertEquals(withoutBridgeMethods, withBridgeMethods); } @TestFactory List ensureSingleTestMethodsExecute() { return Arrays.asList( // dynamicTest("Byte", // () -> assertEquals("[test(Byte) BEGIN, test(N), test(Byte) END, test(Long) BEGIN, test(Long) END]", // execute(2, ByteTestCase.class))), dynamicTest("Short", // () -> assertEquals("[test(Long) BEGIN, test(Long) END, test(Short) BEGIN, test(N), test(Short) END]", // execute(2, ShortTestCase.class)))); } @Test void inheritedNonGenericMethodsAreExecuted() { String b = execute(4, AbstractNonGenericTests.B.class); assertAll("Missing expected test(s) in sequence: " + b, // () -> assertTrue(b.contains("A.test(Number)")), // () -> assertTrue(b.contains("mA()")), // () -> assertTrue(b.contains("mB()")), // () -> assertTrue(b.contains("B.test(Byte)")) // ); String c = execute(5, AbstractNonGenericTests.C.class); assertAll("Missing expected test(s) in sequence: " + c, // () -> assertTrue(c.contains("A.test(Number)")), // () -> assertTrue(c.contains("mA()")), // () -> assertTrue(c.contains("mB()")), // () -> assertTrue(c.contains("mC()")), // () -> assertTrue(c.contains("C.test(Byte)")) // ); } private String execute(int expectedTestFinishedCount, Class testClass) { sequence.clear(); executeTestsForClass(testClass).testEvents()// .assertStatistics(stats -> stats.started(expectedTestFinishedCount)); return sequence.toString(); } } ChildWithBridgeMethods.java000066400000000000000000000016631455764576500352070ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * @since 5.0 */ // modifier "public" is necessary for creating bridge methods by the compiler public class ChildWithBridgeMethods extends PackagePrivateParent { @BeforeEach public void anotherBeforeEach() { BridgeMethodTests.sequence.add("child.anotherBeforeEach()"); } @Test void test() { BridgeMethodTests.sequence.add("child.test()"); } @AfterEach public void anotherAfterEach() { BridgeMethodTests.sequence.add("child.anotherAfterEach()"); } } ChildWithoutBridgeMethods.java000066400000000000000000000016671455764576500357430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * @since 5.0 */ // modifier "public" is *not* present for not creating bridge methods by the compiler class ChildWithoutBridgeMethods extends PackagePrivateParent { @BeforeEach public void anotherBeforeEach() { BridgeMethodTests.sequence.add("child.anotherBeforeEach()"); } @Test void test() { BridgeMethodTests.sequence.add("child.test()"); } @AfterEach public void anotherAfterEach() { BridgeMethodTests.sequence.add("child.anotherAfterEach()"); } } NumberResolver.java000066400000000000000000000025351455764576500336400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; /** * @since 5.0 */ class NumberResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return Number.class.isAssignableFrom(parameterContext.getParameter().getType()); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { Class type = parameterContext.getParameter().getType(); if (type == Number.class) { return 42; } try { return type.getMethod("valueOf", String.class).invoke(null, "123"); } catch (Exception e) { throw new AssertionError("Could not resolve number type: " + type, e); } } } NumberTestGroup.java000066400000000000000000000027231455764576500337720ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; /** * @since 5.0 */ interface NumberTestGroup { class ByteTestCase extends AbstractNumberTests { @Test @Override void test(Byte number) { BridgeMethodTests.sequence.add("test(Byte) BEGIN"); super.test(number); BridgeMethodTests.sequence.add("test(Byte) END"); } @Test void test(Long number) { BridgeMethodTests.sequence.add("test(Long) BEGIN"); assertNotNull(number); assertEquals(123, number.intValue()); BridgeMethodTests.sequence.add("test(Long) END"); } } class ShortTestCase extends AbstractNumberTests { @Test @Override void test(Short number) { BridgeMethodTests.sequence.add("test(Short) BEGIN"); super.test(number); BridgeMethodTests.sequence.add("test(Short) END"); } @Test void test(Long number) { BridgeMethodTests.sequence.add("test(Long) BEGIN"); assertNotNull(number); assertEquals(123, number.intValue()); BridgeMethodTests.sequence.add("test(Long) END"); } } } PackagePrivateParent.java000066400000000000000000000017261455764576500347270ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/bridge/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.bridge; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; /** * @since 5.0 */ class PackagePrivateParent { @BeforeAll static void beforeAll() { BridgeMethodTests.sequence.add("static parent.beforeAll()"); } @AfterAll static void afterAll() { BridgeMethodTests.sequence.add("static parent.afterAll()"); } @BeforeEach public void beforeEach() { BridgeMethodTests.sequence.add("parent.beforeEach()"); } @AfterEach public void afterEach() { BridgeMethodTests.sequence.add("parent.afterEach()"); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/config/000077500000000000000000000000001455764576500301065ustar00rootroot00000000000000CachingJupiterConfigurationTests.java000066400000000000000000000130361455764576500373470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.io.CleanupMode.NEVER; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.only; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import java.util.Optional; import java.util.function.Predicate; import java.util.function.Supplier; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator; /** * Unit tests for {@link CachingJupiterConfiguration}. */ class CachingJupiterConfigurationTests { private final JupiterConfiguration delegate = mock(); private final JupiterConfiguration cache = new CachingJupiterConfiguration(delegate); @Test void cachesDefaultExecutionMode() { when(delegate.getDefaultExecutionMode()).thenReturn(ExecutionMode.CONCURRENT); assertThat(cache.getDefaultExecutionMode()).isEqualTo(ExecutionMode.CONCURRENT); assertThat(cache.getDefaultExecutionMode()).isEqualTo(ExecutionMode.CONCURRENT); verify(delegate, only()).getDefaultExecutionMode(); } @Test void cachesDefaultTestInstanceLifecycle() { when(delegate.getDefaultTestInstanceLifecycle()).thenReturn(Lifecycle.PER_CLASS); assertThat(cache.getDefaultTestInstanceLifecycle()).isEqualTo(Lifecycle.PER_CLASS); assertThat(cache.getDefaultTestInstanceLifecycle()).isEqualTo(Lifecycle.PER_CLASS); verify(delegate, only()).getDefaultTestInstanceLifecycle(); } @Test void cachesExecutionConditionFilter() { Predicate predicate = executionCondition -> true; when(delegate.getExecutionConditionFilter()).thenReturn(predicate); assertThat(cache.getExecutionConditionFilter()).isSameAs(predicate); assertThat(cache.getExecutionConditionFilter()).isSameAs(predicate); verify(delegate, only()).getExecutionConditionFilter(); } @Test void cachesExtensionAutoDetectionEnabled() { when(delegate.isExtensionAutoDetectionEnabled()).thenReturn(true); assertThat(cache.isExtensionAutoDetectionEnabled()).isTrue(); assertThat(cache.isExtensionAutoDetectionEnabled()).isTrue(); verify(delegate, only()).isExtensionAutoDetectionEnabled(); } @Test void cachesParallelExecutionEnabled() { when(delegate.isParallelExecutionEnabled()).thenReturn(true); assertThat(cache.isParallelExecutionEnabled()).isTrue(); assertThat(cache.isParallelExecutionEnabled()).isTrue(); verify(delegate, only()).isParallelExecutionEnabled(); } @Test void cachesDefaultDisplayNameGenerator() { CustomDisplayNameGenerator customDisplayNameGenerator = new CustomDisplayNameGenerator(); when(delegate.getDefaultDisplayNameGenerator()).thenReturn(customDisplayNameGenerator); // call `cache.getDefaultDisplayNameGenerator()` twice to verify the delegate method is called only once. assertThat(cache.getDefaultDisplayNameGenerator()).isSameAs(customDisplayNameGenerator); assertThat(cache.getDefaultDisplayNameGenerator()).isSameAs(customDisplayNameGenerator); verify(delegate, only()).getDefaultDisplayNameGenerator(); } @Test void cachesDefaultTestMethodOrderer() { final Optional methodOrderer = Optional.of(new MethodOrderer.MethodName()); when(delegate.getDefaultTestMethodOrderer()).thenReturn(methodOrderer); // call `cache.getDefaultTestMethodOrderer()` twice to verify the delegate method is called only once. assertThat(cache.getDefaultTestMethodOrderer()).isSameAs(methodOrderer); assertThat(cache.getDefaultTestMethodOrderer()).isSameAs(methodOrderer); verify(delegate, only()).getDefaultTestMethodOrderer(); } @Test void cachesDefaultTempDirCleanupMode() { when(delegate.getDefaultTempDirCleanupMode()).thenReturn(NEVER); // call `cache.getDefaultTempStrategyDirCleanupMode()` twice to verify the delegate method is called only once. assertThat(cache.getDefaultTempDirCleanupMode()).isSameAs(NEVER); assertThat(cache.getDefaultTempDirCleanupMode()).isSameAs(NEVER); verify(delegate, only()).getDefaultTempDirCleanupMode(); } @Test void cachesDefaultTempDirFactorySupplier() { Supplier supplier = mock(); when(delegate.getDefaultTempDirFactorySupplier()).thenReturn(supplier); // call `cache.getDefaultTempDirFactorySupplier()` twice to verify the delegate method is called only once. assertThat(cache.getDefaultTempDirFactorySupplier()).isSameAs(supplier); assertThat(cache.getDefaultTempDirFactorySupplier()).isSameAs(supplier); verify(delegate, only()).getDefaultTempDirFactorySupplier(); } @Test void doesNotCacheRawParameters() { when(delegate.getRawConfigurationParameter("foo")).thenReturn(Optional.of("bar")).thenReturn( Optional.of("baz")); assertThat(cache.getRawConfigurationParameter("foo")).contains("bar"); assertThat(cache.getRawConfigurationParameter("foo")).contains("baz"); verify(delegate, times(2)).getRawConfigurationParameter("foo"); verifyNoMoreInteractions(delegate); } } DefaultJupiterConfigurationTests.java000066400000000000000000000146341455764576500374040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.nio.file.Path; import java.util.Optional; import java.util.function.Supplier; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.Constants; import org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; class DefaultJupiterConfigurationTests { private static final String KEY = DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; @Test void getDefaultTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> new DefaultJupiterConfiguration(null)); assertThat(exception).hasMessage("ConfigurationParameters must not be null"); } @Test void getDefaultTestInstanceLifecycleWithNoConfigParamSet() { JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock()); Lifecycle lifecycle = configuration.getDefaultTestInstanceLifecycle(); assertThat(lifecycle).isEqualTo(PER_METHOD); } @Test void getDefaultTempDirCleanupModeWithNoConfigParamSet() { JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock()); CleanupMode cleanupMode = configuration.getDefaultTempDirCleanupMode(); assertThat(cleanupMode).isEqualTo(ALWAYS); } @Test void getDefaultTestInstanceLifecycleWithConfigParamSet() { assertAll(// () -> assertDefaultConfigParam(null, PER_METHOD), // () -> assertDefaultConfigParam("", PER_METHOD), // () -> assertDefaultConfigParam("bogus", PER_METHOD), // () -> assertDefaultConfigParam(PER_METHOD.name(), PER_METHOD), // () -> assertDefaultConfigParam(PER_METHOD.name().toLowerCase(), PER_METHOD), // () -> assertDefaultConfigParam(" " + PER_METHOD.name() + " ", PER_METHOD), // () -> assertDefaultConfigParam(PER_CLASS.name(), PER_CLASS), // () -> assertDefaultConfigParam(PER_CLASS.name().toLowerCase(), PER_CLASS), // () -> assertDefaultConfigParam(" " + PER_CLASS.name() + " ", Lifecycle.PER_CLASS) // ); } @Test void shouldGetDefaultDisplayNameGeneratorWithConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.of(CustomDisplayNameGenerator.class.getName())); JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters); DisplayNameGenerator defaultDisplayNameGenerator = configuration.getDefaultDisplayNameGenerator(); assertThat(defaultDisplayNameGenerator).isInstanceOf(CustomDisplayNameGenerator.class); } @Test void shouldGetStandardAsDefaultDisplayNameGeneratorWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters); DisplayNameGenerator defaultDisplayNameGenerator = configuration.getDefaultDisplayNameGenerator(); assertThat(defaultDisplayNameGenerator).isInstanceOf(DisplayNameGenerator.Standard.class); } @Test void shouldGetNothingAsDefaultTestMethodOrderWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters); final Optional defaultTestMethodOrder = configuration.getDefaultTestMethodOrderer(); assertThat(defaultTestMethodOrder).isEmpty(); } @Test void shouldGetDefaultTempDirFactorySupplierWithConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.of(CustomFactory.class.getName())); JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters); Supplier supplier = configuration.getDefaultTempDirFactorySupplier(); assertThat(supplier.get()).isInstanceOf(CustomFactory.class); } private static class CustomFactory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) { throw new UnsupportedOperationException(); } } @Test void shouldGetStandardAsDefaultTempDirFactorySupplierWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters); Supplier supplier = configuration.getDefaultTempDirFactorySupplier(); assertThat(supplier.get()).isSameAs(TempDirFactory.Standard.INSTANCE); } private void assertDefaultConfigParam(String configValue, Lifecycle expected) { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.ofNullable(configValue)); Lifecycle lifecycle = new DefaultJupiterConfiguration(configParams).getDefaultTestInstanceLifecycle(); assertThat(lifecycle).isEqualTo(expected); } } InstantiatingConfigurationParameterConverterTests.java000066400000000000000000000156221455764576500430200ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.config; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.engine.Constants.DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Optional; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.ConfigurationParameters; /** * @since 5.5 */ @TrackLogRecords class InstantiatingConfigurationParameterConverterTests { private static final String KEY = DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; @Test void shouldInstantiateConfiguredClass(LogRecordListener listener) { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn(Optional.of(CustomDisplayNameGenerator.class.getName())); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); DisplayNameGenerator displayNameGenerator = converter.get(configurationParameters, KEY).orElseThrow(); assertThat(displayNameGenerator).isInstanceOf(CustomDisplayNameGenerator.class); assertExpectedLogMessage(listener, Level.CONFIG, "Using default display name generator " + "'org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator' set via the " + "'junit.jupiter.displayname.generator.default' configuration parameter."); } @Test void shouldReturnEmptyOptionalIfNoConfigurationFound() { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn(Optional.empty()); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); Optional displayNameGenerator = converter.get(configurationParameters, KEY); assertThat(displayNameGenerator).isEmpty(); } @Test void shouldReturnEmptyOptionalIfConfigurationIsBlank() { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn(Optional.of("")); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); Optional displayNameGenerator = converter.get(configurationParameters, KEY); assertThat(displayNameGenerator).isEmpty(); } @Test void shouldTrimAndInstantiateConfiguredClass(LogRecordListener listener) { ConfigurationParameters configurationParameters = mock(); String classNameWithSpaces = " " + CustomDisplayNameGenerator.class.getName() + " "; when(configurationParameters.get(KEY)).thenReturn(Optional.of(classNameWithSpaces)); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); DisplayNameGenerator displayNameGenerator = converter.get(configurationParameters, KEY).orElseThrow(); assertThat(displayNameGenerator).isInstanceOf(CustomDisplayNameGenerator.class); assertExpectedLogMessage(listener, Level.CONFIG, "Using default display name generator " + "'org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator' set via the " + "'junit.jupiter.displayname.generator.default' configuration parameter."); } @Test void shouldReturnEmptyOptionalIfNoClassFound(LogRecordListener listener) { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn(Optional.of("random-string")); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); Optional displayNameGenerator = converter.get(configurationParameters, KEY); assertThat(displayNameGenerator).isEmpty(); assertExpectedLogMessage(listener, Level.WARNING, "Failed to load default display name generator " + "class 'random-string' set via the 'junit.jupiter.displayname.generator.default' " + "configuration parameter. Falling back to default behavior."); } @Test void shouldReturnEmptyOptionalIfClassFoundIsNotATypeOfExpectedType(LogRecordListener listener) { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn(Optional.of(Object.class.getName())); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); Optional displayNameGenerator = converter.get(configurationParameters, KEY); assertThat(displayNameGenerator).isEmpty(); assertExpectedLogMessage(listener, Level.WARNING, "Failed to load default display name generator class 'java.lang.Object' " + "set via the 'junit.jupiter.displayname.generator.default' configuration parameter. " + "Falling back to default behavior."); } @Test void shouldReturnEmptyOptionalIfClassNameIsNotFullyQualified(LogRecordListener listener) { ConfigurationParameters configurationParameters = mock(); when(configurationParameters.get(KEY)).thenReturn( Optional.of(CustomDisplayNameGenerator.class.getSimpleName())); InstantiatingConfigurationParameterConverter converter = new InstantiatingConfigurationParameterConverter<>( DisplayNameGenerator.class, "display name generator"); Optional displayNameGenerator = converter.get(configurationParameters, KEY); assertThat(displayNameGenerator).isEmpty(); assertExpectedLogMessage(listener, Level.WARNING, "Failed to load default display name generator class 'CustomDisplayNameGenerator' " + "set via the 'junit.jupiter.displayname.generator.default' configuration parameter. " + "Falling back to default behavior."); } private void assertExpectedLogMessage(LogRecordListener listener, Level level, String expectedMessage) { // @formatter:off assertTrue(listener.stream(level) .map(LogRecord::getMessage) .anyMatch(expectedMessage::equals)); // @formatter:on } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/000077500000000000000000000000001455764576500310175ustar00rootroot00000000000000CustomDisplayNameGenerator.java000066400000000000000000000015741455764576500370620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import java.lang.reflect.Method; import org.junit.jupiter.api.DisplayNameGenerator; public class CustomDisplayNameGenerator implements DisplayNameGenerator { @Override public String generateDisplayNameForClass(Class testClass) { return "class-display-name"; } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return "nested-class-display-name"; } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return "method-display-name"; } } DisplayNameUtilsTests.java000066400000000000000000000201471455764576500360610ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.logging.LogRecordListener; /** * Unit tests for {@link DisplayNameUtils}. * * @since 5.5 */ class DisplayNameUtilsTests { @Nested class ClassDisplayNameTests { @Test void shouldGetDisplayNameFromDisplayNameAnnotation() { String displayName = DisplayNameUtils.determineDisplayName(MyTestCase.class, () -> "default-name"); assertThat(displayName).isEqualTo("my-test-case"); } @Test @TrackLogRecords void shouldGetDisplayNameFromSupplierIfNoDisplayNameAnnotationWithBlankStringPresent( LogRecordListener listener) { String displayName = DisplayNameUtils.determineDisplayName(BlankDisplayNameTestCase.class, () -> "default-name"); assertThat(displayName).isEqualTo("default-name"); assertThat(firstWarningLogRecord(listener).getMessage()).isEqualTo( "Configuration error: @DisplayName on [class org.junit.jupiter.engine.descriptor.DisplayNameUtilsTests$BlankDisplayNameTestCase] must be declared with a non-empty value."); } @Test void shouldGetDisplayNameFromSupplierIfNoDisplayNameAnnotationPresent() { String displayName = DisplayNameUtils.determineDisplayName(NotDisplayNameTestCase.class, () -> "default-name"); assertThat(displayName).isEqualTo("default-name"); } @Nested class ClassDisplayNameSupplierTests { private JupiterConfiguration configuration = mock(); @Test void shouldGetDisplayNameFromDisplayNameGenerationAnnotation() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForClass( StandardDisplayNameTestCase.class, configuration); String name = StandardDisplayNameTestCase.class.getName(); String expectedClassName = name.substring(name.lastIndexOf(".") + 1); assertThat(displayName.get()).isEqualTo(expectedClassName); } @Test void shouldGetUnderscoreDisplayNameFromDisplayNameGenerationAnnotation() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForClass( Underscore_DisplayName_TestCase.class, configuration); assertThat(displayName.get()).isEqualTo("DisplayNameUtilsTests$Underscore DisplayName TestCase"); } @Test void shouldGetDisplayNameFromDefaultDisplayNameGenerator() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForClass(MyTestCase.class, configuration); assertThat(displayName.get()).isEqualTo("class-display-name"); } @Test void shouldFallbackOnDefaultDisplayNameGeneratorWhenNullIsGenerated() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForClass( NullDisplayNameTestCase.class, configuration); assertThat(displayName.get()).isEqualTo("class-display-name"); } } } @Nested class NestedClassDisplayNameTests { private JupiterConfiguration configuration = mock(); @Test void shouldGetDisplayNameFromDisplayNameGenerationAnnotation() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForNestedClass( StandardDisplayNameTestCase.class, configuration); assertThat(displayName.get()).isEqualTo(StandardDisplayNameTestCase.class.getSimpleName()); } @Test void shouldGetDisplayNameFromDefaultDisplayNameGenerator() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForNestedClass( NestedTestCase.class, configuration); assertThat(displayName.get()).isEqualTo("nested-class-display-name"); } @Test void shouldFallbackOnDefaultDisplayNameGeneratorWhenNullIsGenerated() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Supplier displayName = DisplayNameUtils.createDisplayNameSupplierForNestedClass( NullDisplayNameTestCase.NestedTestCase.class, configuration); assertThat(displayName.get()).isEqualTo("nested-class-display-name"); } } @Nested class MethodDisplayNameTests { private JupiterConfiguration configuration = mock(); @Test void shouldGetDisplayNameFromDisplayNameGenerationAnnotation() throws Exception { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); Method method = MyTestCase.class.getDeclaredMethod("test1"); String displayName = DisplayNameUtils.determineDisplayNameForMethod(StandardDisplayNameTestCase.class, method, configuration); assertThat(displayName).isEqualTo("test1()"); } @Test void shouldGetDisplayNameFromDefaultNameGenerator() throws Exception { Method method = MyTestCase.class.getDeclaredMethod("test1"); when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); String displayName = DisplayNameUtils.determineDisplayNameForMethod(NotDisplayNameTestCase.class, method, configuration); assertThat(displayName).isEqualTo("method-display-name"); } @Test void shouldFallbackOnDefaultDisplayNameGeneratorWhenNullIsGenerated() throws Exception { Method method = NullDisplayNameTestCase.class.getDeclaredMethod("test"); when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); String displayName = DisplayNameUtils.determineDisplayNameForMethod(NullDisplayNameTestCase.class, method, configuration); assertThat(displayName).isEqualTo("method-display-name"); } } private LogRecord firstWarningLogRecord(LogRecordListener listener) throws AssertionError { return listener.stream(DisplayNameUtils.class, Level.WARNING).findFirst().orElseThrow( () -> new AssertionError("Failed to find warning log record")); } @DisplayName("my-test-case") @DisplayNameGeneration(value = CustomDisplayNameGenerator.class) static class MyTestCase { void test1() { } } @DisplayName("") static class BlankDisplayNameTestCase { } @DisplayNameGeneration(value = DisplayNameGenerator.Standard.class) static class StandardDisplayNameTestCase { } @DisplayNameGeneration(value = DisplayNameGenerator.ReplaceUnderscores.class) static class Underscore_DisplayName_TestCase { } static class NotDisplayNameTestCase { } @Nested class NestedTestCase { } @DisplayNameGeneration(value = NullDisplayNameGenerator.class) static class NullDisplayNameTestCase { @Test void test() { } @Nested class NestedTestCase { } } static class NullDisplayNameGenerator implements DisplayNameGenerator { @Override public String generateDisplayNameForClass(Class testClass) { return null; } @Override public String generateDisplayNameForNestedClass(Class nestedClass) { return null; } @Override public String generateDisplayNameForMethod(Class testClass, Method testMethod) { return null; } } } ExtensionContextTests.java000066400000000000000000000363721455764576500361620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.config.DefaultJupiterConfiguration; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.DefaultTestInstances; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.hierarchical.OpenTest4JAwareThrowableCollector; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; /** * Unit tests for concrete implementations of {@link ExtensionContext}: * {@link JupiterEngineExtensionContext}, {@link ClassExtensionContext}, and * {@link MethodExtensionContext}. * * @since 5.0 * @see org.junit.jupiter.engine.execution.ExtensionValuesStoreTests */ public class ExtensionContextTests { private final JupiterConfiguration configuration = mock(); @BeforeEach void setUp() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); when(configuration.getDefaultExecutionMode()).thenReturn(ExecutionMode.SAME_THREAD); when(configuration.getDefaultClassesExecutionMode()).thenReturn(ExecutionMode.SAME_THREAD); } @Test void fromJupiterEngineDescriptor() { JupiterEngineDescriptor engineTestDescriptor = new JupiterEngineDescriptor( UniqueId.root("engine", "junit-jupiter"), configuration); JupiterEngineExtensionContext engineContext = new JupiterEngineExtensionContext(null, engineTestDescriptor, configuration, null); // @formatter:off assertAll("engineContext", () -> assertThat(engineContext.getElement()).isEmpty(), () -> assertThat(engineContext.getTestClass()).isEmpty(), () -> assertThat(engineContext.getTestInstance()).isEmpty(), () -> assertThat(engineContext.getTestMethod()).isEmpty(), () -> assertThrows(PreconditionViolationException.class, () -> engineContext.getRequiredTestClass()), () -> assertThrows(PreconditionViolationException.class, () -> engineContext.getRequiredTestInstance()), () -> assertThrows(PreconditionViolationException.class, () -> engineContext.getRequiredTestMethod()), () -> assertThat(engineContext.getDisplayName()).isEqualTo(engineTestDescriptor.getDisplayName()), () -> assertThat(engineContext.getParent()).isEmpty(), () -> assertThat(engineContext.getRoot()).isSameAs(engineContext), () -> assertThat(engineContext.getExecutionMode()).isEqualTo(ExecutionMode.SAME_THREAD) ); // @formatter:on } @Test @SuppressWarnings("resource") void fromClassTestDescriptor() { NestedClassTestDescriptor nestedClassDescriptor = nestedClassDescriptor(); ClassTestDescriptor outerClassDescriptor = outerClassDescriptor(nestedClassDescriptor); ClassExtensionContext outerExtensionContext = new ClassExtensionContext(null, null, outerClassDescriptor, configuration, null, null); // @formatter:off assertAll("outerContext", () -> assertThat(outerExtensionContext.getElement()).contains(OuterClass.class), () -> assertThat(outerExtensionContext.getTestClass()).contains(OuterClass.class), () -> assertThat(outerExtensionContext.getTestInstance()).isEmpty(), () -> assertThat(outerExtensionContext.getTestMethod()).isEmpty(), () -> assertThat(outerExtensionContext.getRequiredTestClass()).isEqualTo(OuterClass.class), () -> assertThrows(PreconditionViolationException.class, () -> outerExtensionContext.getRequiredTestInstance()), () -> assertThrows(PreconditionViolationException.class, () -> outerExtensionContext.getRequiredTestMethod()), () -> assertThat(outerExtensionContext.getDisplayName()).isEqualTo(outerClassDescriptor.getDisplayName()), () -> assertThat(outerExtensionContext.getParent()).isEmpty(), () -> assertThat(outerExtensionContext.getExecutionMode()).isEqualTo(ExecutionMode.SAME_THREAD) ); // @formatter:on ClassExtensionContext nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, null, nestedClassDescriptor, configuration, null, null); assertThat(nestedExtensionContext.getParent()).containsSame(outerExtensionContext); } @Test @SuppressWarnings("resource") void tagsCanBeRetrievedInExtensionContext() { NestedClassTestDescriptor nestedClassDescriptor = nestedClassDescriptor(); ClassTestDescriptor outerClassDescriptor = outerClassDescriptor(nestedClassDescriptor); TestMethodTestDescriptor methodTestDescriptor = methodDescriptor(); outerClassDescriptor.addChild(methodTestDescriptor); ClassExtensionContext outerExtensionContext = new ClassExtensionContext(null, null, outerClassDescriptor, configuration, null, null); assertThat(outerExtensionContext.getTags()).containsExactly("outer-tag"); assertThat(outerExtensionContext.getRoot()).isSameAs(outerExtensionContext); ClassExtensionContext nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, null, nestedClassDescriptor, configuration, null, null); assertThat(nestedExtensionContext.getTags()).containsExactlyInAnyOrder("outer-tag", "nested-tag"); assertThat(nestedExtensionContext.getRoot()).isSameAs(outerExtensionContext); MethodExtensionContext methodExtensionContext = new MethodExtensionContext(outerExtensionContext, null, methodTestDescriptor, configuration, new OpenTest4JAwareThrowableCollector(), null); methodExtensionContext.setTestInstances(DefaultTestInstances.of(new OuterClass())); assertThat(methodExtensionContext.getTags()).containsExactlyInAnyOrder("outer-tag", "method-tag"); assertThat(methodExtensionContext.getRoot()).isSameAs(outerExtensionContext); } @Test @SuppressWarnings("resource") void fromMethodTestDescriptor() { TestMethodTestDescriptor methodTestDescriptor = methodDescriptor(); ClassTestDescriptor classTestDescriptor = outerClassDescriptor(methodTestDescriptor); JupiterEngineDescriptor engineDescriptor = new JupiterEngineDescriptor(UniqueId.forEngine("junit-jupiter"), configuration); engineDescriptor.addChild(classTestDescriptor); Object testInstance = new OuterClass(); Method testMethod = methodTestDescriptor.getTestMethod(); JupiterEngineExtensionContext engineExtensionContext = new JupiterEngineExtensionContext(null, engineDescriptor, configuration, null); ClassExtensionContext classExtensionContext = new ClassExtensionContext(engineExtensionContext, null, classTestDescriptor, configuration, null, null); MethodExtensionContext methodExtensionContext = new MethodExtensionContext(classExtensionContext, null, methodTestDescriptor, configuration, new OpenTest4JAwareThrowableCollector(), null); methodExtensionContext.setTestInstances(DefaultTestInstances.of(testInstance)); // @formatter:off assertAll("methodContext", () -> assertThat(methodExtensionContext.getElement()).contains(testMethod), () -> assertThat(methodExtensionContext.getTestClass()).contains(OuterClass.class), () -> assertThat(methodExtensionContext.getTestInstance()).contains(testInstance), () -> assertThat(methodExtensionContext.getTestMethod()).contains(testMethod), () -> assertThat(methodExtensionContext.getRequiredTestClass()).isEqualTo(OuterClass.class), () -> assertThat(methodExtensionContext.getRequiredTestInstance()).isEqualTo(testInstance), () -> assertThat(methodExtensionContext.getRequiredTestMethod()).isEqualTo(testMethod), () -> assertThat(methodExtensionContext.getDisplayName()).isEqualTo(methodTestDescriptor.getDisplayName()), () -> assertThat(methodExtensionContext.getParent()).contains(classExtensionContext), () -> assertThat(methodExtensionContext.getRoot()).isSameAs(engineExtensionContext), () -> assertThat(methodExtensionContext.getExecutionMode()).isEqualTo(ExecutionMode.SAME_THREAD) ); // @formatter:on } @Test @SuppressWarnings("resource") void reportEntriesArePublishedToExecutionContext() { ClassTestDescriptor classTestDescriptor = outerClassDescriptor(null); EngineExecutionListener engineExecutionListener = Mockito.spy(EngineExecutionListener.class); ExtensionContext extensionContext = new ClassExtensionContext(null, engineExecutionListener, classTestDescriptor, configuration, null, null); Map map1 = Collections.singletonMap("key", "value"); Map map2 = Collections.singletonMap("other key", "other value"); extensionContext.publishReportEntry(map1); extensionContext.publishReportEntry(map2); extensionContext.publishReportEntry("3rd key", "third value"); extensionContext.publishReportEntry("status message"); ArgumentCaptor entryCaptor = ArgumentCaptor.forClass(ReportEntry.class); Mockito.verify(engineExecutionListener, Mockito.times(4)).reportingEntryPublished( ArgumentMatchers.eq(classTestDescriptor), entryCaptor.capture()); ReportEntry reportEntry1 = entryCaptor.getAllValues().get(0); ReportEntry reportEntry2 = entryCaptor.getAllValues().get(1); ReportEntry reportEntry3 = entryCaptor.getAllValues().get(2); ReportEntry reportEntry4 = entryCaptor.getAllValues().get(3); assertEquals(map1, reportEntry1.getKeyValuePairs()); assertEquals(map2, reportEntry2.getKeyValuePairs()); assertEquals("third value", reportEntry3.getKeyValuePairs().get("3rd key")); assertEquals("status message", reportEntry4.getKeyValuePairs().get("value")); } @Test @SuppressWarnings("resource") void usingStore() { TestMethodTestDescriptor methodTestDescriptor = methodDescriptor(); ClassTestDescriptor classTestDescriptor = outerClassDescriptor(methodTestDescriptor); ExtensionContext parentContext = new ClassExtensionContext(null, null, classTestDescriptor, configuration, null, null); MethodExtensionContext childContext = new MethodExtensionContext(parentContext, null, methodTestDescriptor, configuration, new OpenTest4JAwareThrowableCollector(), null); childContext.setTestInstances(DefaultTestInstances.of(new OuterClass())); ExtensionContext.Store childStore = childContext.getStore(Namespace.GLOBAL); ExtensionContext.Store parentStore = parentContext.getStore(Namespace.GLOBAL); final Object key1 = "key 1"; final String value1 = "a value"; childStore.put(key1, value1); assertEquals(value1, childStore.get(key1)); assertEquals(value1, childStore.remove(key1)); assertNull(childStore.get(key1)); childStore.put(key1, value1); assertEquals(value1, childStore.get(key1)); assertEquals(value1, childStore.remove(key1, String.class)); assertNull(childStore.get(key1)); final Object key2 = "key 2"; final String value2 = "other value"; assertEquals(value2, childStore.getOrComputeIfAbsent(key2, key -> value2)); assertEquals(value2, childStore.getOrComputeIfAbsent(key2, key -> value2, String.class)); assertEquals(value2, childStore.get(key2)); assertEquals(value2, childStore.get(key2, String.class)); final Object parentKey = "parent key"; final String parentValue = "parent value"; parentStore.put(parentKey, parentValue); assertEquals(parentValue, childStore.getOrComputeIfAbsent(parentKey, k -> "a different value")); assertEquals(parentValue, childStore.get(parentKey)); } @TestFactory Stream configurationParameter() throws Exception { JupiterConfiguration echo = new DefaultJupiterConfiguration(new EchoParameters()); String key = "123"; Optional expected = Optional.of(key); UniqueId engineUniqueId = UniqueId.parse("[engine:junit-jupiter]"); JupiterEngineDescriptor engineDescriptor = new JupiterEngineDescriptor(engineUniqueId, configuration); UniqueId classUniqueId = UniqueId.parse("[engine:junit-jupiter]/[class:MyClass]"); ClassTestDescriptor classTestDescriptor = new ClassTestDescriptor(classUniqueId, getClass(), configuration); Method method = getClass().getDeclaredMethod("configurationParameter"); UniqueId methodUniqueId = UniqueId.parse("[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]"); TestMethodTestDescriptor methodTestDescriptor = new TestMethodTestDescriptor(methodUniqueId, getClass(), method, configuration); return Stream.of( // (ExtensionContext) new JupiterEngineExtensionContext(null, engineDescriptor, echo, null), // new ClassExtensionContext(null, null, classTestDescriptor, echo, null, null), // new MethodExtensionContext(null, null, methodTestDescriptor, echo, null, null) // ).map(context -> dynamicTest(context.getClass().getSimpleName(), () -> assertEquals(expected, context.getConfigurationParameter(key)))); } private NestedClassTestDescriptor nestedClassDescriptor() { return new NestedClassTestDescriptor(UniqueId.root("nested-class", "NestedClass"), OuterClass.NestedClass.class, configuration); } private ClassTestDescriptor outerClassDescriptor(TestDescriptor child) { ClassTestDescriptor classTestDescriptor = new ClassTestDescriptor(UniqueId.root("class", "OuterClass"), OuterClass.class, configuration); if (child != null) { classTestDescriptor.addChild(child); } return classTestDescriptor; } private TestMethodTestDescriptor methodDescriptor() { try { return new TestMethodTestDescriptor(UniqueId.root("method", "aMethod"), OuterClass.class, OuterClass.class.getDeclaredMethod("aMethod"), configuration); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } @Tag("outer-tag") static class OuterClass { @Tag("nested-tag") class NestedClass { } @Tag("method-tag") void aMethod() { } } private static class EchoParameters implements ConfigurationParameters { @Override public Optional get(String key) { return Optional.of(key); } @Override public Optional getBoolean(String key) { throw new UnsupportedOperationException("getBoolean(String) should not be called"); } @Override @SuppressWarnings("deprecation") public int size() { throw new UnsupportedOperationException("size() should not be called"); } @Override public Set keySet() { throw new UnsupportedOperationException("keySet() should not be called"); } } } JupiterTestDescriptorTests.java000066400000000000000000000343741455764576500371620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.JupiterTestDescriptorTests.StaticTestCase.StaticTestCaseLevel2; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.MethodSource; /** * Unit tests for {@link ClassTestDescriptor}, {@link NestedClassTestDescriptor}, * and {@link TestMethodTestDescriptor}. * * @since 5.0 * @see org.junit.jupiter.engine.descriptor.LifecycleMethodUtilsTests */ class JupiterTestDescriptorTests { private static final UniqueId uniqueId = UniqueId.root("enigma", "foo"); private final JupiterConfiguration configuration = mock(); @BeforeEach void setUp() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); when(configuration.getDefaultExecutionMode()).thenReturn(ExecutionMode.SAME_THREAD); } @Test void constructFromClass() { ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCase.class, configuration); assertEquals(TestCase.class, descriptor.getTestClass()); assertThat(descriptor.getTags()).containsExactly(TestTag.create("inherited-class-level-tag"), TestTag.create("classTag1"), TestTag.create("classTag2")); } @Test void constructFromClassWithInvalidBeforeAllDeclaration() { // Note: if we can instantiate the descriptor, then the invalid configuration // will not be reported during the test engine discovery phase. ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidBeforeAllMethod.class, configuration); assertEquals(TestCaseWithInvalidBeforeAllMethod.class, descriptor.getTestClass()); } @Test void constructFromClassWithInvalidAfterAllDeclaration() { // Note: if we can instantiate the descriptor, then the invalid configuration // will not be reported during the test engine discovery phase. ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidAfterAllMethod.class, configuration); assertEquals(TestCaseWithInvalidAfterAllMethod.class, descriptor.getTestClass()); } @Test void constructFromClassWithInvalidBeforeEachDeclaration() { // Note: if we can instantiate the descriptor, then the invalid configuration // will not be reported during the test engine discovery phase. ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidBeforeEachMethod.class, configuration); assertEquals(TestCaseWithInvalidBeforeEachMethod.class, descriptor.getTestClass()); } @Test void constructFromClassWithInvalidAfterEachDeclaration() { // Note: if we can instantiate the descriptor, then the invalid configuration // will not be reported during the test engine discovery phase. ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidAfterEachMethod.class, configuration); assertEquals(TestCaseWithInvalidAfterEachMethod.class, descriptor.getTestClass()); } @Test void constructFromMethod() throws Exception { Class testClass = TestCase.class; Method testMethod = testClass.getDeclaredMethod("test"); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, testClass, testMethod, configuration); assertEquals(uniqueId, descriptor.getUniqueId()); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test()", descriptor.getDisplayName(), "display name:"); assertEquals("test()", descriptor.getLegacyReportingName(), "legacy name:"); } @Test void constructFromMethodWithAnnotations() throws Exception { JupiterTestDescriptor classDescriptor = new ClassTestDescriptor(uniqueId, TestCase.class, configuration); Method testMethod = TestCase.class.getDeclaredMethod("foo"); TestMethodTestDescriptor methodDescriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); classDescriptor.addChild(methodDescriptor); assertEquals(testMethod, methodDescriptor.getTestMethod()); assertEquals("custom test name", methodDescriptor.getDisplayName(), "display name:"); assertEquals("foo()", methodDescriptor.getLegacyReportingName(), "legacy name:"); List tags = methodDescriptor.getTags().stream().map(TestTag::getName).collect(toList()); assertThat(tags).containsExactlyInAnyOrder("inherited-class-level-tag", "classTag1", "classTag2", "methodTag1", "methodTag2"); } @Test void constructFromMethodWithCustomTestAnnotation() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("customTestAnnotation"); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("custom name", descriptor.getDisplayName(), "display name:"); assertEquals("customTestAnnotation()", descriptor.getLegacyReportingName(), "legacy name:"); assertThat(descriptor.getTags()).containsExactly(TestTag.create("custom-tag")); } @Test void constructFromMethodWithParameters() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("test", String.class, BigDecimal.class); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test(String, BigDecimal)", descriptor.getDisplayName(), "display name"); assertEquals("test(String, BigDecimal)", descriptor.getLegacyReportingName(), "legacy name"); } @Test void constructFromMethodWithPrimitiveArrayParameter() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("test", int[].class); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test(int[])", descriptor.getDisplayName(), "display name"); assertEquals("test(int[])", descriptor.getLegacyReportingName(), "legacy name"); } @Test void constructFromMethodWithObjectArrayParameter() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("test", String[].class); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test(String[])", descriptor.getDisplayName(), "display name"); assertEquals("test(String[])", descriptor.getLegacyReportingName(), "legacy name"); } @Test void constructFromMethodWithMultidimensionalPrimitiveArrayParameter() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("test", int[][][][][].class); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test(int[][][][][])", descriptor.getDisplayName(), "display name"); assertEquals("test(int[][][][][])", descriptor.getLegacyReportingName(), "legacy name"); } @Test void constructFromMethodWithMultidimensionalObjectArrayParameter() throws Exception { Method testMethod = TestCase.class.getDeclaredMethod("test", String[][][][][].class); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, TestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); assertEquals("test(String[][][][][])", descriptor.getDisplayName(), "display name"); assertEquals("test(String[][][][][])", descriptor.getLegacyReportingName(), "legacy name"); } @Test void constructFromInheritedMethod() throws Exception { Method testMethod = ConcreteTestCase.class.getMethod("theTest"); TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor(uniqueId, ConcreteTestCase.class, testMethod, configuration); assertEquals(testMethod, descriptor.getTestMethod()); Optional sourceOptional = descriptor.getSource(); assertThat(sourceOptional).containsInstanceOf(MethodSource.class); MethodSource methodSource = (MethodSource) sourceOptional.orElseThrow(); assertEquals(ConcreteTestCase.class.getName(), methodSource.getClassName()); assertEquals("theTest", methodSource.getMethodName()); } @Test void shouldTakeCustomMethodNameDescriptorFromConfigurationIfPresent() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); ClassBasedTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, getClass(), configuration); assertEquals("class-display-name", descriptor.getDisplayName()); assertEquals(getClass().getName(), descriptor.getLegacyReportingName()); descriptor = new NestedClassTestDescriptor(uniqueId, NestedTestCase.class, configuration); assertEquals("nested-class-display-name", descriptor.getDisplayName()); assertEquals(NestedTestCase.class.getName(), descriptor.getLegacyReportingName()); descriptor = new ClassTestDescriptor(uniqueId, StaticTestCase.class, configuration); assertEquals("class-display-name", descriptor.getDisplayName()); assertEquals(StaticTestCase.class.getName(), descriptor.getLegacyReportingName()); descriptor = new ClassTestDescriptor(uniqueId, StaticTestCaseLevel2.class, configuration); assertEquals("class-display-name", descriptor.getDisplayName()); assertEquals(StaticTestCaseLevel2.class.getName(), descriptor.getLegacyReportingName()); } @Test void defaultDisplayNamesForTestClasses() { ClassBasedTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, getClass(), configuration); assertEquals(getClass().getSimpleName(), descriptor.getDisplayName()); assertEquals(getClass().getName(), descriptor.getLegacyReportingName()); descriptor = new NestedClassTestDescriptor(uniqueId, NestedTestCase.class, configuration); assertEquals(NestedTestCase.class.getSimpleName(), descriptor.getDisplayName()); assertEquals(NestedTestCase.class.getName(), descriptor.getLegacyReportingName()); descriptor = new ClassTestDescriptor(uniqueId, StaticTestCase.class, configuration); String staticDisplayName = getClass().getSimpleName() + "$" + StaticTestCase.class.getSimpleName(); assertEquals(staticDisplayName, descriptor.getDisplayName()); assertEquals(StaticTestCase.class.getName(), descriptor.getLegacyReportingName()); descriptor = new ClassTestDescriptor(uniqueId, StaticTestCaseLevel2.class, configuration); staticDisplayName += "$" + StaticTestCaseLevel2.class.getSimpleName(); assertEquals(staticDisplayName, descriptor.getDisplayName()); assertEquals(StaticTestCaseLevel2.class.getName(), descriptor.getLegacyReportingName()); } @Test void enclosingClassesAreDerivedFromParent() { ClassBasedTestDescriptor parentDescriptor = new ClassTestDescriptor(uniqueId, StaticTestCase.class, configuration); ClassBasedTestDescriptor nestedDescriptor = new NestedClassTestDescriptor(uniqueId, NestedTestCase.class, configuration); assertThat(parentDescriptor.getEnclosingTestClasses()).isEmpty(); assertThat(nestedDescriptor.getEnclosingTestClasses()).isEmpty(); parentDescriptor.addChild(nestedDescriptor); assertThat(parentDescriptor.getEnclosingTestClasses()).isEmpty(); assertThat(nestedDescriptor.getEnclosingTestClasses()).containsExactly(StaticTestCase.class); } // ------------------------------------------------------------------------- @Test @DisplayName("custom name") @Tag(" custom-tag ") @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface CustomTestAnnotation { } @Tag("inherited-class-level-tag") private static abstract class AbstractTestCase { } @Tag("classTag1") @Tag("classTag2") @DisplayName("custom class name") @SuppressWarnings("unused") private static class TestCase extends AbstractTestCase { void test() { } void test(String txt, BigDecimal sum) { } void test(int[] nums) { } void test(int[][][][][] nums) { } void test(String[] info) { } void test(String[][][][][] info) { } @Test @DisplayName("custom test name") @Tag("methodTag1") @Tag("methodTag2") @Tag("tag containing whitespace") void foo() { } @CustomTestAnnotation void customTestAnnotation() { } } private static class TestCaseWithInvalidBeforeAllMethod { // must be static @BeforeAll void beforeAll() { } @Test void test() { } } private static class TestCaseWithInvalidAfterAllMethod { // must be static @AfterAll void afterAll() { } @Test void test() { } } private static class TestCaseWithInvalidBeforeEachMethod { // must NOT be static @BeforeEach static void beforeEach() { } @Test void test() { } } private static class TestCaseWithInvalidAfterEachMethod { // must NOT be static @AfterEach static void afterEach() { } @Test void test() { } } @Nested class NestedTestCase { } static class StaticTestCase { static class StaticTestCaseLevel2 { } } private abstract static class AbstractTestBase { @Test public void theTest() { } } private static class ConcreteTestCase extends AbstractTestBase { } } LifecycleMethodUtilsTests.java000066400000000000000000000134741455764576500367200ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findAfterAllMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findAfterEachMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findBeforeAllMethods; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.findBeforeEachMethods; import java.lang.reflect.Method; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.platform.commons.JUnitException; /** * Unit tests for {@link LifecycleMethodUtils}. * * @since 5.0 */ class LifecycleMethodUtilsTests { @Test void findNonVoidBeforeAllMethodsWithStandardLifecycle() { JUnitException exception = assertThrows(JUnitException.class, () -> findBeforeAllMethods(TestCaseWithNonVoidLifecyleMethods.class, true)); assertEquals( "@BeforeAll method 'java.lang.Double org.junit.jupiter.engine.descriptor.TestCaseWithNonVoidLifecyleMethods.cc()' must not return a value.", exception.getMessage()); } @Test void findNonVoidAfterAllMethodsWithStandardLifecycle() { JUnitException exception = assertThrows(JUnitException.class, () -> findAfterAllMethods(TestCaseWithNonVoidLifecyleMethods.class, true)); assertEquals( "@AfterAll method 'java.lang.String org.junit.jupiter.engine.descriptor.TestCaseWithNonVoidLifecyleMethods.dd()' must not return a value.", exception.getMessage()); } @Test void findNonVoidBeforeEachMethodsWithStandardLifecycle() { JUnitException exception = assertThrows(JUnitException.class, () -> findBeforeEachMethods(TestCaseWithNonVoidLifecyleMethods.class)); assertEquals( "@BeforeEach method 'java.lang.String org.junit.jupiter.engine.descriptor.TestCaseWithNonVoidLifecyleMethods.aa()' must not return a value.", exception.getMessage()); } @Test void findNonVoidAfterEachMethodsWithStandardLifecycle() { JUnitException exception = assertThrows(JUnitException.class, () -> findAfterEachMethods(TestCaseWithNonVoidLifecyleMethods.class)); assertEquals( "@AfterEach method 'int org.junit.jupiter.engine.descriptor.TestCaseWithNonVoidLifecyleMethods.bb()' must not return a value.", exception.getMessage()); } @Test void findBeforeEachMethodsWithStandardLifecycle() { List methods = findBeforeEachMethods(TestCaseWithStandardLifecycle.class); assertThat(namesOf(methods)).containsExactlyInAnyOrder("nine", "ten"); } @Test void findAfterEachMethodsWithStandardLifecycle() { List methods = findAfterEachMethods(TestCaseWithStandardLifecycle.class); assertThat(namesOf(methods)).containsExactlyInAnyOrder("eleven", "twelve"); } @Test void findBeforeAllMethodsWithStandardLifecycleAndWithoutRequiringStatic() { List methods = findBeforeAllMethods(TestCaseWithStandardLifecycle.class, false); assertThat(namesOf(methods)).containsExactly("one"); } @Test void findBeforeAllMethodsWithStandardLifecycleAndRequiringStatic() { JUnitException exception = assertThrows(JUnitException.class, () -> findBeforeAllMethods(TestCaseWithStandardLifecycle.class, true)); assertEquals( "@BeforeAll method 'void org.junit.jupiter.engine.descriptor.TestCaseWithStandardLifecycle.one()' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).", exception.getMessage()); } @Test void findBeforeAllMethodsWithLifeCyclePerClassAndRequiringStatic() { List methods = findBeforeAllMethods(TestCaseWithLifecyclePerClass.class, false); assertThat(namesOf(methods)).containsExactlyInAnyOrder("three", "four"); } @Test void findAfterAllMethodsWithStandardLifecycleAndWithoutRequiringStatic() { List methods = findAfterAllMethods(TestCaseWithStandardLifecycle.class, false); assertThat(namesOf(methods)).containsExactlyInAnyOrder("five", "six"); } @Test void findAfterAllMethodsWithStandardLifecycleAndRequiringStatic() { assertThrows(JUnitException.class, () -> findAfterAllMethods(TestCaseWithStandardLifecycle.class, true)); } @Test void findAfterAllMethodsWithLifeCyclePerClassAndRequiringStatic() { List methods = findAfterAllMethods(TestCaseWithLifecyclePerClass.class, false); assertThat(namesOf(methods)).containsExactlyInAnyOrder("seven", "eight"); } private static List namesOf(List methods) { return methods.stream().map(Method::getName).collect(toList()); } } class TestCaseWithStandardLifecycle { @BeforeAll void one() { } @BeforeEach void nine() { } @BeforeEach void ten() { } @AfterEach void eleven() { } @AfterEach void twelve() { } @AfterAll void five() { } @AfterAll void six() { } } @TestInstance(Lifecycle.PER_CLASS) class TestCaseWithLifecyclePerClass { @BeforeAll void three() { } @BeforeAll void four() { } @AfterAll void seven() { } @AfterAll void eight() { } } class TestCaseWithNonVoidLifecyleMethods { @BeforeEach String aa() { return null; } @AfterEach int bb() { return 1; } @BeforeAll Double cc() { return null; } @AfterAll String dd() { return ""; } } NamespaceTests.java000066400000000000000000000017551455764576500345320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; public class NamespaceTests { @Test void namespacesEqualForSamePartsSequence() { Namespace ns1 = Namespace.create("part1", "part2"); Namespace ns2 = Namespace.create("part1", "part2"); assertEquals(ns1, ns2); } @Test void orderOfNamespacePartsDoesMatter() { Namespace ns1 = Namespace.create("part1", "part2"); Namespace ns2 = Namespace.create("part2", "part1"); assertNotEquals(ns1, ns2); } } TestFactoryTestDescriptorTests.java000066400000000000000000000150031455764576500377730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; import java.lang.reflect.Method; import java.net.URI; import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClasspathResourceSource; import org.junit.platform.engine.support.descriptor.DirectorySource; import org.junit.platform.engine.support.descriptor.FilePosition; import org.junit.platform.engine.support.descriptor.FileSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.engine.support.descriptor.UriSource; import org.junit.platform.engine.support.hierarchical.OpenTest4JAwareThrowableCollector; /** * Unit tests for {@link TestFactoryTestDescriptor}. * * @since 5.0 */ class TestFactoryTestDescriptorTests { /** * @since 5.3 */ @Nested class TestSources { @Test void classpathResourceSourceFromUriWithFilePosition() { FilePosition position = FilePosition.from(42, 21); URI uri = URI.create("classpath:/test.js?line=42&column=21"); TestSource testSource = TestFactoryTestDescriptor.fromUri(uri); assertThat(testSource).isInstanceOf(ClasspathResourceSource.class); ClasspathResourceSource source = (ClasspathResourceSource) testSource; assertThat(source.getClasspathResourceName()).isEqualTo("test.js"); assertThat(source.getPosition()).hasValue(position); } @Test void fileSourceFromUriWithFilePosition() { File file = new File("src/test/resources/log4j2-test.xml"); assertThat(file).isFile(); FilePosition position = FilePosition.from(42, 21); URI uri = URI.create(file.toURI().toString() + "?line=42&column=21"); TestSource testSource = TestFactoryTestDescriptor.fromUri(uri); assertThat(testSource).isInstanceOf(FileSource.class); FileSource source = (FileSource) testSource; assertThat(source.getFile().getAbsolutePath()).isEqualTo(file.getAbsolutePath()); assertThat(source.getPosition()).hasValue(position); } @Test void directorySourceFromUri() { File file = new File("src/test/resources"); assertThat(file).isDirectory(); URI uri = file.toURI(); TestSource testSource = TestFactoryTestDescriptor.fromUri(uri); assertThat(testSource).isInstanceOf(DirectorySource.class); DirectorySource source = (DirectorySource) testSource; assertThat(source.getFile().getAbsolutePath()).isEqualTo(file.getAbsolutePath()); } @Test void defaultUriSourceFromUri() { File file = new File("src/test/resources"); assertThat(file).isDirectory(); URI uri = URI.create("https://example.com?foo=bar&line=42"); TestSource testSource = TestFactoryTestDescriptor.fromUri(uri); assertThat(testSource).isInstanceOf(UriSource.class); assertThat(testSource.getClass().getSimpleName()).isEqualTo("DefaultUriSource"); UriSource source = (UriSource) testSource; assertThat(source.getUri()).isEqualTo(uri); } @Test void methodSourceFromUri() { URI uri = URI.create("method:org.junit.Foo#bar(java.lang.String,%20java.lang.String[])"); TestSource testSource = TestFactoryTestDescriptor.fromUri(uri); assertThat(testSource).isInstanceOf(MethodSource.class); assertThat(testSource.getClass().getSimpleName()).isEqualTo("MethodSource"); MethodSource source = (MethodSource) testSource; assertThat(source.getClassName()).isEqualTo("org.junit.Foo"); assertThat(source.getMethodName()).isEqualTo("bar"); assertThat(source.getMethodParameterTypes()).isEqualTo("java.lang.String, java.lang.String[]"); } } @Nested class Streams { private JupiterEngineExecutionContext context; private ExtensionContext extensionContext; private TestFactoryTestDescriptor descriptor; private boolean isClosed; private JupiterConfiguration jupiterConfiguration; @BeforeEach void before() throws Exception { jupiterConfiguration = mock(); when(jupiterConfiguration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); extensionContext = mock(); isClosed = false; context = new JupiterEngineExecutionContext(null, null) // .extend() // .withThrowableCollector(new OpenTest4JAwareThrowableCollector()) // .withExtensionContext(extensionContext) // .withExtensionRegistry(mock()) // .build(); Method testMethod = CustomStreamTestCase.class.getDeclaredMethod("customStream"); descriptor = new TestFactoryTestDescriptor(UniqueId.forEngine("engine"), CustomStreamTestCase.class, testMethod, jupiterConfiguration); when(extensionContext.getTestMethod()).thenReturn(Optional.of(testMethod)); } @Test void streamsFromTestFactoriesShouldBeClosed() { Stream dynamicTestStream = Stream.empty(); prepareMockForTestInstanceWithCustomStream(dynamicTestStream); descriptor.invokeTestMethod(context, mock()); assertTrue(isClosed); } @Test void streamsFromTestFactoriesShouldBeClosedWhenTheyThrow() { Stream integerStream = Stream.of(1, 2); prepareMockForTestInstanceWithCustomStream(integerStream); descriptor.invokeTestMethod(context, mock()); assertTrue(isClosed); } private void prepareMockForTestInstanceWithCustomStream(Stream stream) { Stream mockStream = stream.onClose(() -> isClosed = true); when(extensionContext.getRequiredTestInstance()).thenReturn(new CustomStreamTestCase(mockStream)); } } private static class CustomStreamTestCase { private final Stream mockStream; CustomStreamTestCase(Stream mockStream) { this.mockStream = mockStream; } @TestFactory Stream customStream() { return mockStream; } } } TestInstanceLifecycleUtilsTests.java000066400000000000000000000104171455764576500400760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; import static org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils.getTestInstanceLifecycle; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.engine.config.DefaultJupiterConfiguration; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; /** * Unit tests for {@link TestInstanceLifecycleUtils}. * *

NOTE: it doesn't make sense to unit test the JVM system property fallback * support in this test class since that feature is a concrete implementation * detail of {@code LauncherConfigurationParameters} which necessitates an * integration test via the {@code Launcher} API. * * @since 5.0 */ class TestInstanceLifecycleUtilsTests { private static final String KEY = DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; @Test void getTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> getTestInstanceLifecycle(null, new DefaultJupiterConfiguration(mock()))); assertThat(exception).hasMessage("testClass must not be null"); exception = assertThrows(PreconditionViolationException.class, () -> getTestInstanceLifecycle(getClass(), null)); assertThat(exception).hasMessage("configuration must not be null"); } @Test void getTestInstanceLifecycleWithNoConfigParamSet() { Lifecycle lifecycle = getTestInstanceLifecycle(getClass(), new DefaultJupiterConfiguration(mock())); assertThat(lifecycle).isEqualTo(PER_METHOD); } @Test void getTestInstanceLifecycleWithConfigParamSet() { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.of(PER_CLASS.name().toLowerCase())); Lifecycle lifecycle = getTestInstanceLifecycle(getClass(), new DefaultJupiterConfiguration(configParams)); assertThat(lifecycle).isEqualTo(PER_CLASS); } @Test void getTestInstanceLifecycleWithLocalConfigThatOverridesCustomDefaultSetViaConfigParam() { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.of(PER_CLASS.name().toLowerCase())); Lifecycle lifecycle = getTestInstanceLifecycle(TestCase.class, new DefaultJupiterConfiguration(configParams)); assertThat(lifecycle).isEqualTo(PER_METHOD); } @Test void getTestInstanceLifecycleFromMetaAnnotationWithNoConfigParamSet() { Class testClass = BaseMetaAnnotatedTestCase.class; Lifecycle lifecycle = getTestInstanceLifecycle(testClass, new DefaultJupiterConfiguration(mock())); assertThat(lifecycle).isEqualTo(PER_CLASS); } @Test void getTestInstanceLifecycleFromSpecializedClassWithNoConfigParamSet() { Class testClass = SpecializedTestCase.class; Lifecycle lifecycle = getTestInstanceLifecycle(testClass, new DefaultJupiterConfiguration(mock())); assertThat(lifecycle).isEqualTo(PER_CLASS); } @TestInstance(Lifecycle.PER_METHOD) private static class TestCase { } @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @TestInstance(Lifecycle.PER_CLASS) private @interface PerClassLifeCycle { } @PerClassLifeCycle private static class BaseMetaAnnotatedTestCase { } private static class SpecializedTestCase extends BaseMetaAnnotatedTestCase { } } TestTemplateInvocationTestDescriptorTests.java000066400000000000000000000041111455764576500421670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.UniqueId; class TestTemplateInvocationTestDescriptorTests { @Test void invocationsDoNotDeclareExclusiveResources() throws Exception { Class testClass = MyTestCase.class; Method testTemplateMethod = testClass.getDeclaredMethod("testTemplate"); JupiterConfiguration configuration = mock(); when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); TestTemplateTestDescriptor parent = new TestTemplateTestDescriptor(UniqueId.root("segment", "template"), testClass, testTemplateMethod, configuration); TestTemplateInvocationContext invocationContext = mock(); when(invocationContext.getDisplayName(anyInt())).thenReturn("invocation"); TestTemplateInvocationTestDescriptor testDescriptor = new TestTemplateInvocationTestDescriptor( parent.getUniqueId().append(TestTemplateInvocationTestDescriptor.SEGMENT_TYPE, "1"), testClass, testTemplateMethod, invocationContext, 1, configuration); assertThat(parent.getExclusiveResources()).hasSize(1); assertThat(testDescriptor.getExclusiveResources()).isEmpty(); } static class MyTestCase { @TestTemplate @ResourceLock("a") void testTemplate() { } } } TestTemplateTestDescriptorTests.java000066400000000000000000000076511455764576500401510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor; import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Set; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; /** * Unit tests for {@link TestTemplateTestDescriptor}. * * @since 5.0 */ class TestTemplateTestDescriptorTests { private JupiterConfiguration jupiterConfiguration = mock(); @Test void inheritsTagsFromParent() throws Exception { UniqueId rootUniqueId = UniqueId.root("segment", "template"); UniqueId parentUniqueId = rootUniqueId.append("class", "myClass"); AbstractTestDescriptor parent = containerTestDescriptorWithTags(parentUniqueId, singleton(TestTag.create("foo"))); when(jupiterConfiguration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); TestTemplateTestDescriptor testDescriptor = new TestTemplateTestDescriptor( parentUniqueId.append("tmp", "testTemplate()"), MyTestCase.class, MyTestCase.class.getDeclaredMethod("testTemplate"), jupiterConfiguration); parent.addChild(testDescriptor); assertThat(testDescriptor.getTags()).containsExactlyInAnyOrder(TestTag.create("foo"), TestTag.create("bar"), TestTag.create("baz")); } @Test void shouldUseCustomDisplayNameGeneratorIfPresentFromConfiguration() throws Exception { UniqueId rootUniqueId = UniqueId.root("segment", "template"); UniqueId parentUniqueId = rootUniqueId.append("class", "myClass"); AbstractTestDescriptor parent = containerTestDescriptorWithTags(parentUniqueId, singleton(TestTag.create("foo"))); when(jupiterConfiguration.getDefaultDisplayNameGenerator()).thenReturn(new CustomDisplayNameGenerator()); TestTemplateTestDescriptor testDescriptor = new TestTemplateTestDescriptor( parentUniqueId.append("tmp", "testTemplate()"), MyTestCase.class, MyTestCase.class.getDeclaredMethod("testTemplate"), jupiterConfiguration); parent.addChild(testDescriptor); assertThat(testDescriptor.getDisplayName()).isEqualTo("method-display-name"); } @Test void shouldUseStandardDisplayNameGeneratorIfConfigurationNotPresent() throws Exception { UniqueId rootUniqueId = UniqueId.root("segment", "template"); UniqueId parentUniqueId = rootUniqueId.append("class", "myClass"); AbstractTestDescriptor parent = containerTestDescriptorWithTags(parentUniqueId, singleton(TestTag.create("foo"))); when(jupiterConfiguration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); TestTemplateTestDescriptor testDescriptor = new TestTemplateTestDescriptor( parentUniqueId.append("tmp", "testTemplate()"), MyTestCase.class, MyTestCase.class.getDeclaredMethod("testTemplate"), jupiterConfiguration); parent.addChild(testDescriptor); assertThat(testDescriptor.getDisplayName()).isEqualTo("testTemplate()"); } private AbstractTestDescriptor containerTestDescriptorWithTags(UniqueId uniqueId, Set tags) { return new AbstractTestDescriptor(uniqueId, "testDescriptor with tags") { @Override public Type getType() { return Type.CONTAINER; } @Override public Set getTags() { return tags; } }; } static class MyTestCase { @Tag("bar") @Tag("baz") @TestTemplate void testTemplate() { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/subpackage/000077500000000000000000000000001455764576500331245ustar00rootroot00000000000000Class1WithTestCases.java000066400000000000000000000007571455764576500375220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor.subpackage; import org.junit.jupiter.api.Test; /** * @since 5.0 */ public class Class1WithTestCases { @Test void test1() { } } Class2WithTestCases.java000066400000000000000000000007571455764576500375230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor.subpackage; import org.junit.jupiter.api.Test; /** * @since 5.0 */ public class Class2WithTestCases { @Test void test2() { } } ClassWithStaticInnerTestCases.java000066400000000000000000000012271455764576500415760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor.subpackage; import org.junit.jupiter.api.Test; /** * @since 5.0 */ public class ClassWithStaticInnerTestCases { public static class ShouldBeDiscovered { @Test void test1() { } } @SuppressWarnings("unused") private static class ShouldNotBeDiscovered { @Test void test2() { } } } ClassWithoutTestCases.java000066400000000000000000000006611455764576500401630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.descriptor.subpackage; /** * @since 5.0 */ public class ClassWithoutTestCases { } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/000077500000000000000000000000001455764576500306505ustar00rootroot00000000000000DiscoverySelectorResolverTests.java000066400000000000000000001043571455764576500376630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static java.util.Collections.singleton; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor.DYNAMIC_CONTAINER_SEGMENT_TYPE; import static org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor.DYNAMIC_TEST_SEGMENT_TYPE; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.engineId; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForClass; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForMethod; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestFactoryMethod; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestTemplateMethod; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTopLevelClass; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.SelectorResolutionResult.Status.FAILED; import static org.junit.platform.engine.SelectorResolutionResult.Status.RESOLVED; import static org.junit.platform.engine.SelectorResolutionResult.Status.UNRESOLVED; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.discovery.PackageNameFilter.excludePackageNames; import static org.junit.platform.engine.discovery.PackageNameFilter.includePackageNames; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.DynamicDescendantFilter; import org.junit.jupiter.engine.descriptor.Filterable; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.descriptor.JupiterTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor; import org.junit.jupiter.engine.descriptor.subpackage.Class1WithTestCases; import org.junit.jupiter.engine.descriptor.subpackage.Class2WithTestCases; import org.junit.jupiter.engine.descriptor.subpackage.ClassWithStaticInnerTestCases; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.mockito.ArgumentCaptor; /** * @since 5.0 */ class DiscoverySelectorResolverTests { private final JupiterConfiguration configuration = mock(); private final LauncherDiscoveryListener discoveryListener = mock(); private final JupiterEngineDescriptor engineDescriptor = new JupiterEngineDescriptor(engineId(), configuration); @BeforeEach void setUp() { when(configuration.getDefaultDisplayNameGenerator()).thenReturn(new DisplayNameGenerator.Standard()); when(configuration.getDefaultExecutionMode()).thenReturn(ExecutionMode.SAME_THREAD); } @Test void nonTestClassResolution() { resolve(request().selectors(selectClass(NonTestClass.class))); assertTrue(engineDescriptor.getDescendants().isEmpty()); } @Test void doesNotAttemptToResolveMethodsForNonTestClasses() { var methodSelector = selectMethod(NonTestClass.class, "doesNotExist"); resolve(request().selectors(methodSelector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); assertUnresolved(methodSelector); } @Test void abstractClassResolution() { resolve(request().selectors(selectClass(AbstractTestClass.class))); assertTrue(engineDescriptor.getDescendants().isEmpty()); assertUnresolved(selectClass(AbstractTestClass.class)); } @Test void singleClassResolution() { ClassSelector selector = selectClass(MyTestClass.class); resolve(request().selectors(selector)); assertEquals(4, engineDescriptor.getDescendants().size()); assertUniqueIdsForMyTestClass(uniqueIds()); } @Test void classResolutionForNonexistentClass() { ClassSelector selector = selectClass("org.example.DoesNotExist"); resolve(request().selectors(selector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get()).hasMessageContaining("Could not load class with name"); } @Test void duplicateClassSelectorOnlyResolvesOnce() { resolve(request().selectors( // selectClass(MyTestClass.class), // selectClass(MyTestClass.class) // )); assertEquals(4, engineDescriptor.getDescendants().size()); assertUniqueIdsForMyTestClass(uniqueIds()); } @Test void twoClassesResolution() { ClassSelector selector1 = selectClass(MyTestClass.class); ClassSelector selector2 = selectClass(YourTestClass.class); resolve(request().selectors(selector1, selector2)); assertEquals(7, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertUniqueIdsForMyTestClass(uniqueIds); assertThat(uniqueIds).contains(uniqueIdForClass(YourTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(YourTestClass.class, "test3()")); assertThat(uniqueIds).contains(uniqueIdForMethod(YourTestClass.class, "test4()")); } private void assertUniqueIdsForMyTestClass(List uniqueIds) { assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test2()")); assertThat(uniqueIds).contains(uniqueIdForTestFactoryMethod(MyTestClass.class, "dynamicTest()")); } @Test void classResolutionOfStaticNestedClass() { ClassSelector selector = selectClass(OtherTestClass.NestedTestClass.class); resolve(request().selectors(selector)); assertEquals(3, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test6()")); } @Test void methodResolution() throws NoSuchMethodException { Method test1 = MyTestClass.class.getDeclaredMethod("test1"); MethodSelector selector = selectMethod(test1.getDeclaringClass(), test1); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); } @Test void methodResolutionFromInheritedMethod() throws NoSuchMethodException { MethodSelector selector = selectMethod(HerTestClass.class, MyTestClass.class.getDeclaredMethod("test1")); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(HerTestClass.class, "test1()")); } @Test void resolvingSelectorOfNonTestMethodResolvesNothing() throws NoSuchMethodException { Method notATest = MyTestClass.class.getDeclaredMethod("notATest"); MethodSelector selector = selectMethod(notATest.getDeclaringClass(), notATest); resolve(request().selectors(selector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); } @Test void methodResolutionForNonexistentClass() { String className = "org.example.DoesNotExist"; String methodName = "bogus"; MethodSelector selector = selectMethod(className, methodName, ""); resolve(request().selectors(selector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get())// .isInstanceOf(PreconditionViolationException.class)// .hasMessageStartingWith("Could not load class with name: " + className); } @Test void methodResolutionForNonexistentMethod() { MethodSelector selector = selectMethod(MyTestClass.class, "bogus", ""); resolve(request().selectors(selector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get()).hasMessageContaining("Could not find method"); } @Test void classResolutionByUniqueId() { UniqueIdSelector selector = selectUniqueId(uniqueIdForClass(MyTestClass.class).toString()); resolve(request().selectors(selector)); assertEquals(4, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertUniqueIdsForMyTestClass(uniqueIds); } @Test void staticNestedClassResolutionByUniqueId() { UniqueIdSelector selector = selectUniqueId(uniqueIdForClass(OtherTestClass.NestedTestClass.class).toString()); resolve(request().selectors(selector)); assertEquals(3, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test6()")); } @Test void methodOfInnerClassByUniqueId() { UniqueIdSelector selector = selectUniqueId( uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()").toString()); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); } @Test void resolvingUniqueIdWithUnknownSegmentTypeResolvesNothing() { UniqueId uniqueId = engineId().append("bogus", "enigma"); UniqueIdSelector selector = selectUniqueId(uniqueId); resolve(request().selectors(selector)); assertTrue(engineDescriptor.getDescendants().isEmpty()); assertUnresolved(selector); } @Test void resolvingUniqueIdOfNonTestMethodResolvesNothing() { UniqueIdSelector selector = selectUniqueId(uniqueIdForMethod(MyTestClass.class, "notATest()")); resolve(request().selectors(selector)); assertThat(engineDescriptor.getDescendants()).isEmpty(); assertUnresolved(selector); } @Test void methodResolutionByUniqueIdWithMissingMethodName() { UniqueId uniqueId = uniqueIdForMethod(getClass(), "()"); resolve(request().selectors(selectUniqueId(uniqueId))); assertTrue(engineDescriptor.getDescendants().isEmpty()); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get())// .isInstanceOf(PreconditionViolationException.class)// .hasMessageStartingWith("Method [()] does not match pattern"); } @Test void methodResolutionByUniqueIdWithMissingParameters() { UniqueId uniqueId = uniqueIdForMethod(getClass(), "methodName"); resolve(request().selectors(selectUniqueId(uniqueId))); assertThat(engineDescriptor.getDescendants()).isEmpty(); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get())// .isInstanceOf(PreconditionViolationException.class)// .hasMessageStartingWith("Method [methodName] does not match pattern"); } @Test void methodResolutionByUniqueIdWithBogusParameters() { UniqueId uniqueId = uniqueIdForMethod(getClass(), "methodName(java.lang.String, junit.foo.Enigma)"); resolve(request().selectors(selectUniqueId(uniqueId))); assertTrue(engineDescriptor.getDescendants().isEmpty()); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get())// .isInstanceOf(JUnitException.class)// .hasMessage("Failed to load parameter type [%s] for method [%s] in class [%s].", "junit.foo.Enigma", "methodName", getClass().getName()); } @Test void methodResolutionByUniqueId() { UniqueIdSelector selector = selectUniqueId(uniqueIdForMethod(MyTestClass.class, "test1()").toString()); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); } @Test void methodResolutionByUniqueIdFromInheritedClass() { UniqueIdSelector selector = selectUniqueId(uniqueIdForMethod(HerTestClass.class, "test1()").toString()); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(HerTestClass.class, "test1()")); } @Test void methodResolutionByUniqueIdWithParams() { UniqueIdSelector selector = selectUniqueId( uniqueIdForMethod(HerTestClass.class, "test7(java.lang.String)").toString()); resolve(request().selectors(selector)); assertEquals(2, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(HerTestClass.class, "test7(java.lang.String)")); } @Test void resolvingUniqueIdWithWrongParamsResolvesNothing() { UniqueId uniqueId = uniqueIdForMethod(HerTestClass.class, "test7(java.math.BigDecimal)"); resolve(request().selectors(selectUniqueId(uniqueId))); assertTrue(engineDescriptor.getDescendants().isEmpty()); assertUnresolved(selectUniqueId(uniqueId)); } @Test void twoMethodResolutionsByUniqueId() { UniqueIdSelector selector1 = selectUniqueId(uniqueIdForMethod(MyTestClass.class, "test1()").toString()); UniqueIdSelector selector2 = selectUniqueId(uniqueIdForMethod(MyTestClass.class, "test2()").toString()); // adding same selector twice should have no effect resolve(request().selectors(selector1, selector2, selector2)); assertEquals(3, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test2()")); TestDescriptor classFromMethod1 = descriptorByUniqueId( uniqueIdForMethod(MyTestClass.class, "test1()")).getParent().get(); TestDescriptor classFromMethod2 = descriptorByUniqueId( uniqueIdForMethod(MyTestClass.class, "test2()")).getParent().get(); assertEquals(classFromMethod1, classFromMethod2); assertSame(classFromMethod1, classFromMethod2); } @Test void packageResolutionUsingExplicitBasePackage() { PackageSelector selector = selectPackage("org.junit.jupiter.engine.descriptor.subpackage"); resolve(request().selectors(selector)); assertEquals(6, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(Class1WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class1WithTestCases.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForClass(Class2WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class2WithTestCases.class, "test2()")); assertThat(uniqueIds).contains( uniqueIdForMethod(ClassWithStaticInnerTestCases.ShouldBeDiscovered.class, "test1()")); } @Test void packageResolutionUsingDefaultPackage() throws Exception { resolve(request().selectors(selectPackage(""))); // 150 is completely arbitrary. The actual number is likely much higher. assertThat(engineDescriptor.getDescendants())// .describedAs("Too few test descriptors in classpath")// .hasSizeGreaterThan(150); List uniqueIds = uniqueIds(); assertThat(uniqueIds)// .describedAs("Failed to pick up DefaultPackageTestCase via classpath scanning")// .contains(uniqueIdForClass(ReflectionUtils.tryToLoadClass("DefaultPackageTestCase").get())); assertThat(uniqueIds).contains(uniqueIdForClass(Class1WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class1WithTestCases.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForClass(Class2WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class2WithTestCases.class, "test2()")); } @Test void classpathResolution() throws Exception { Path classpath = Paths.get( DiscoverySelectorResolverTests.class.getProtectionDomain().getCodeSource().getLocation().toURI()); List selectors = selectClasspathRoots(singleton(classpath)); resolve(request().selectors(selectors)); // 150 is completely arbitrary. The actual number is likely much higher. assertThat(engineDescriptor.getDescendants())// .describedAs("Too few test descriptors in classpath")// .hasSizeGreaterThan(150); List uniqueIds = uniqueIds(); assertThat(uniqueIds)// .describedAs("Failed to pick up DefaultPackageTestCase via classpath scanning")// .contains(uniqueIdForClass(ReflectionUtils.tryToLoadClass("DefaultPackageTestCase").get())); assertThat(uniqueIds).contains(uniqueIdForClass(Class1WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class1WithTestCases.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForClass(Class2WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class2WithTestCases.class, "test2()")); assertThat(uniqueIds).contains( uniqueIdForMethod(ClassWithStaticInnerTestCases.ShouldBeDiscovered.class, "test1()")); } @Test void classpathResolutionForJarFiles() throws Exception { URL jarUrl = getClass().getResource("/jupiter-testjar.jar"); Path path = Paths.get(jarUrl.toURI()); List selectors = selectClasspathRoots(singleton(path)); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try (URLClassLoader classLoader = new URLClassLoader(new URL[] { jarUrl })) { Thread.currentThread().setContextClassLoader(classLoader); resolve(request().selectors(selectors)); assertThat(uniqueIds()) // .contains(uniqueIdForTopLevelClass("com.example.project.FirstTest")) // .contains(uniqueIdForTopLevelClass("com.example.project.SecondTest")); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Test void nestedTestResolutionFromBaseClass() { ClassSelector selector = selectClass(TestCaseWithNesting.class); resolve(request().selectors(selector)); List uniqueIds = uniqueIds(); assertThat(uniqueIds).hasSize(6); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(TestCaseWithNesting.class, "testA()")); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.class, "testB()")); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class)); assertThat(uniqueIds).contains( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, "testC()")); } @Test void nestedTestResolutionFromNestedTestClass() { ClassSelector selector = selectClass(TestCaseWithNesting.NestedTestCase.class); resolve(request().selectors(selector)); List uniqueIds = uniqueIds(); assertThat(uniqueIds).hasSize(5); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.class, "testB()")); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class)); assertThat(uniqueIds).contains( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, "testC()")); } @Test void nestedTestResolutionFromUniqueId() { UniqueIdSelector selector = selectUniqueId( uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class).toString()); resolve(request().selectors(selector)); List uniqueIds = uniqueIds(); assertThat(uniqueIds).hasSize(4); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class)); assertThat(uniqueIds).contains( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, "testC()")); } @Test void doubleNestedTestResolutionFromClass() { ClassSelector selector = selectClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class); resolve(request().selectors(selector)); List uniqueIds = uniqueIds(); assertThat(uniqueIds).hasSize(4); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class)); assertThat(uniqueIds).contains( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, "testC()")); } @Test void methodResolutionInDoubleNestedTestClass() throws NoSuchMethodException { MethodSelector selector = selectMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class.getDeclaredMethod("testC")); resolve(request().selectors(selector)); assertEquals(4, engineDescriptor.getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class)); assertThat(uniqueIds).contains( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.DoubleNestedTestCase.class, "testC()")); } @Test void nestedTestResolutionFromUniqueIdToMethod() { UniqueIdSelector selector = selectUniqueId( uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.class, "testB()").toString()); resolve(request().selectors(selector)); List uniqueIds = uniqueIds(); assertThat(uniqueIds).hasSize(3); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(TestCaseWithNesting.NestedTestCase.class, "testB()")); } @Test void testFactoryMethodResolutionByUniqueId() { Class clazz = MyTestClass.class; UniqueId factoryUid = uniqueIdForTestFactoryMethod(clazz, "dynamicTest()"); resolve(request().selectors(selectUniqueId(factoryUid))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); } @Test void testTemplateMethodResolutionByUniqueId() { Class clazz = TestClassWithTemplate.class; UniqueId templateUid = uniqueIdForTestTemplateMethod(clazz, "testTemplate()"); resolve(request().selectors(selectUniqueId(templateUid))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), templateUid); } @Test void resolvingDynamicTestByUniqueIdResolvesUpToParentTestFactory() { Class clazz = MyTestClass.class; UniqueId factoryUid = uniqueIdForTestFactoryMethod(clazz, "dynamicTest()"); UniqueId dynamicTestUid = factoryUid.append(DYNAMIC_TEST_SEGMENT_TYPE, "#1"); UniqueId differentDynamicTestUid = factoryUid.append(DYNAMIC_TEST_SEGMENT_TYPE, "#2"); resolve(request().selectors(selectUniqueId(dynamicTestUid))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); assertThat(dynamicDescendantFilter.test(dynamicTestUid, 42)).isTrue(); assertThat(dynamicDescendantFilter.test(differentDynamicTestUid, 42)).isFalse(); assertAllSelectorsResolved(); } @Test void resolvingDynamicContainerByUniqueIdResolvesUpToParentTestFactory() { Class clazz = MyTestClass.class; UniqueId factoryUid = uniqueIdForTestFactoryMethod(clazz, "dynamicTest()"); UniqueId dynamicContainerUid = factoryUid.append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#1"); UniqueId differentDynamicContainerUid = factoryUid.append(DYNAMIC_CONTAINER_SEGMENT_TYPE, "#2"); UniqueId dynamicTestUid = dynamicContainerUid.append(DYNAMIC_TEST_SEGMENT_TYPE, "#1"); UniqueId differentDynamicTestUid = dynamicContainerUid.append(DYNAMIC_TEST_SEGMENT_TYPE, "#2"); resolve(request().selectors(selectUniqueId(dynamicTestUid))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); assertThat(dynamicDescendantFilter.test(dynamicTestUid, 42)).isTrue(); assertThat(dynamicDescendantFilter.test(differentDynamicContainerUid, 42)).isFalse(); assertThat(dynamicDescendantFilter.test(differentDynamicTestUid, 42)).isFalse(); assertAllSelectorsResolved(); } @Test void resolvingDynamicTestByUniqueIdAndTestFactoryByMethodSelectorResolvesTestFactory() { Class clazz = MyTestClass.class; UniqueId factoryUid = uniqueIdForTestFactoryMethod(clazz, "dynamicTest()"); UniqueId dynamicTestUid = factoryUid.append(DYNAMIC_TEST_SEGMENT_TYPE, "#1"); resolve(request().selectors(selectUniqueId(dynamicTestUid), selectMethod(clazz, "dynamicTest"))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); assertThat(dynamicDescendantFilter.test(UniqueId.root("foo", "bar"), 42)).isTrue(); } private DynamicDescendantFilter getDynamicDescendantFilter(TestDescriptor testDescriptor) { assertThat(testDescriptor).isInstanceOf(JupiterTestDescriptor.class); return ((Filterable) testDescriptor).getDynamicDescendantFilter(); } @Test void resolvingTestTemplateInvocationByUniqueIdResolvesOnlyUpToParentTestTemplate() { Class clazz = TestClassWithTemplate.class; UniqueId templateUid = uniqueIdForTestTemplateMethod(clazz, "testTemplate()"); UniqueId invocationUid = templateUid.append(TestTemplateInvocationTestDescriptor.SEGMENT_TYPE, "#1"); resolve(request().selectors(selectUniqueId(invocationUid))); assertThat(engineDescriptor.getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), templateUid); } @Test void includingPackageNameFilterExcludesClassesInNonMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( includePackageNames("org.junit.jupiter.engine.unknown"))); assertThat(engineDescriptor.getDescendants()).isEmpty(); } @Test void includingPackageNameFilterIncludesClassesInMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( includePackageNames("org.junit.jupiter.engine"))); assertThat(engineDescriptor.getDescendants()).hasSize(3); } @Test void excludingPackageNameFilterExcludesClassesInMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( excludePackageNames("org.junit.jupiter.engine"))); assertThat(engineDescriptor.getDescendants()).isEmpty(); } @Test void excludingPackageNameFilterIncludesClassesInNonMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( excludePackageNames("org.junit.jupiter.engine.unknown"))); assertThat(engineDescriptor.getDescendants()).hasSize(3); } @Test void classNamePatternFilterExcludesNonMatchingClasses() { resolve(request().selectors(selectClass(MatchingClass.class), selectClass(OtherClass.class)).filters( includeClassNamePatterns(".*MatchingClass"))); assertThat(engineDescriptor.getDescendants()).hasSize(3); } private void resolve(LauncherDiscoveryRequestBuilder builder) { new DiscoverySelectorResolver().resolveSelectors(builder.build(), engineDescriptor); } private TestDescriptor descriptorByUniqueId(UniqueId uniqueId) { return engineDescriptor.getDescendants().stream().filter( d -> d.getUniqueId().equals(uniqueId)).findFirst().get(); } private List uniqueIds() { return engineDescriptor.getDescendants().stream().map(TestDescriptor::getUniqueId).collect(toList()); } private LauncherDiscoveryRequestBuilder request() { return LauncherDiscoveryRequestBuilder.request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .listeners(discoveryListener); } private void assertAllSelectorsResolved() { ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(SelectorResolutionResult.class); verify(discoveryListener).selectorProcessed(eq(UniqueId.forEngine("junit-jupiter")), any(), resultCaptor.capture()); assertThat(resultCaptor.getAllValues()) // .flatExtracting(SelectorResolutionResult::getStatus) // .allMatch(Predicate.isEqual(RESOLVED)); } private void assertUnresolved(DiscoverySelector selector) { var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(UNRESOLVED); } private SelectorResolutionResult verifySelectorProcessed(DiscoverySelector selector) { ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(SelectorResolutionResult.class); verify(discoveryListener).selectorProcessed(eq(UniqueId.forEngine("junit-jupiter")), eq(selector), resultCaptor.capture()); return resultCaptor.getValue(); } } // ----------------------------------------------------------------------------- class NonTestClass { } abstract class AbstractTestClass { @Test void test() { } } class MyTestClass { @Test void test1() { } @Test void test2() { } void notATest() { } @TestFactory Stream dynamicTest() { return new ArrayList().stream(); } } class YourTestClass { @Test void test3() { } @Test void test4() { } } class HerTestClass extends MyTestClass { @Test void test7(String param) { } } class OtherTestClass { static class NestedTestClass { @Test void test5() { } @Test void test6() { } } } class TestCaseWithNesting { @Test void testA() { } @Nested class NestedTestCase { @Test void testB() { } @Nested class DoubleNestedTestCase { @Test void testC() { } } } } class TestClassWithTemplate { @TestTemplate void testTemplate() { } } class MatchingClass { @Nested class NestedClass { @Test void test() { } } } class OtherClass { @Test void test() { } } DiscoveryTests.java000066400000000000000000000176231455764576500344370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestTemplateMethod; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectNestedMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.List; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * Test correct test discovery in simple test classes for the {@link JupiterTestEngine}. * * @since 5.0 */ class DiscoveryTests extends AbstractJupiterTestEngineTests { @Test void discoverTestClass() { LauncherDiscoveryRequest request = request().selectors(selectClass(LocalTestCase.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(7, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void doNotDiscoverAbstractTestClass() { LauncherDiscoveryRequest request = request().selectors(selectClass(AbstractTestCase.class)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(0, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverMethodByUniqueId() { LauncherDiscoveryRequest request = request().selectors( selectUniqueId(JupiterUniqueIdBuilder.uniqueIdForMethod(LocalTestCase.class, "test1()"))).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverMethodByUniqueIdForOverloadedMethod() { LauncherDiscoveryRequest request = request().selectors( selectUniqueId(JupiterUniqueIdBuilder.uniqueIdForMethod(LocalTestCase.class, "test4()"))).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverMethodByUniqueIdForOverloadedMethodVariantThatAcceptsArguments() { LauncherDiscoveryRequest request = request().selectors(selectUniqueId(JupiterUniqueIdBuilder.uniqueIdForMethod( LocalTestCase.class, "test4(" + TestInfo.class.getName() + ")"))).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverMethodByMethodReference() throws NoSuchMethodException { Method testMethod = LocalTestCase.class.getDeclaredMethod("test3", new Class[0]); LauncherDiscoveryRequest request = request().selectors(selectMethod(LocalTestCase.class, testMethod)).build(); TestDescriptor engineDescriptor = discoverTests(request); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverMultipleMethodsOfSameClass() { LauncherDiscoveryRequest request = request().selectors(selectMethod(LocalTestCase.class, "test1"), selectMethod(LocalTestCase.class, "test2")).build(); TestDescriptor engineDescriptor = discoverTests(request); assertThat(engineDescriptor.getChildren()).hasSize(1); TestDescriptor classDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(classDescriptor.getChildren()).hasSize(2); } @Test void discoverCompositeSpec() { LauncherDiscoveryRequest spec = request().selectors( selectUniqueId(JupiterUniqueIdBuilder.uniqueIdForMethod(LocalTestCase.class, "test2()")), selectClass(LocalTestCase.class)).build(); TestDescriptor engineDescriptor = discoverTests(spec); assertEquals(7, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverTestTemplateMethodByUniqueId() { LauncherDiscoveryRequest spec = request().selectors( selectUniqueId(uniqueIdForTestTemplateMethod(TestTemplateClass.class, "testTemplate()"))).build(); TestDescriptor engineDescriptor = discoverTests(spec); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverTestTemplateMethodByMethodSelector() { LauncherDiscoveryRequest spec = request().selectors( selectMethod(TestTemplateClass.class, "testTemplate")).build(); TestDescriptor engineDescriptor = discoverTests(spec); assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void discoverDeeplyNestedTestMethodByNestedMethodSelector() throws Exception { var selector = selectNestedMethod( List.of(TestCaseWithExtendedNested.class, TestCaseWithExtendedNested.ConcreteInner1.class), AbstractSuperClass.NestedInAbstractClass.class, AbstractSuperClass.NestedInAbstractClass.class.getDeclaredMethod("test")); LauncherDiscoveryRequest spec = request().selectors(selector).build(); TestDescriptor engineDescriptor = discoverTests(spec); ClassTestDescriptor topLevelClassDescriptor = (ClassTestDescriptor) getOnlyElement( engineDescriptor.getChildren()); assertThat(topLevelClassDescriptor.getTestClass()).isEqualTo(TestCaseWithExtendedNested.class); NestedClassTestDescriptor firstLevelNestedClassDescriptor = (NestedClassTestDescriptor) getOnlyElement( topLevelClassDescriptor.getChildren()); assertThat(firstLevelNestedClassDescriptor.getTestClass()).isEqualTo( TestCaseWithExtendedNested.ConcreteInner1.class); NestedClassTestDescriptor secondLevelNestedClassDescriptor = (NestedClassTestDescriptor) getOnlyElement( firstLevelNestedClassDescriptor.getChildren()); assertThat(secondLevelNestedClassDescriptor.getTestClass()).isEqualTo( AbstractSuperClass.NestedInAbstractClass.class); TestMethodTestDescriptor methodDescriptor = (TestMethodTestDescriptor) getOnlyElement( secondLevelNestedClassDescriptor.getChildren()); assertThat(methodDescriptor.getTestMethod().getName()).isEqualTo("test"); } // ------------------------------------------------------------------- private static abstract class AbstractTestCase { @Test void abstractTest() { } } static class LocalTestCase { @Test void test1() { } @Test void test2() { } @Test void test3() { } @Test void test4() { } @Test void test4(TestInfo testInfo) { } @CustomTestAnnotation void customTestAnnotation() { /* no-op */ } } @Test @Retention(RetentionPolicy.RUNTIME) @interface CustomTestAnnotation { } static class TestTemplateClass { @TestTemplate void testTemplate() { } } static abstract class AbstractSuperClass { @Nested class NestedInAbstractClass { @Test void test() { } } } static class TestCaseWithExtendedNested { @Nested class ConcreteInner1 extends AbstractSuperClass { } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/000077500000000000000000000000001455764576500327735ustar00rootroot00000000000000IsInnerClassTests.java000066400000000000000000000022331455764576500371370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; import java.util.function.Predicate; import org.junit.jupiter.api.Test; /** * @since 5.0 */ class IsInnerClassTests { private final Predicate> isInnerClass = new IsInnerClass(); @Test void innerClassEvaluatesToTrue() { assertThat(isInnerClass).accepts(InnerClassesTestCase.InnerClass.class); } @Test void staticNestedClassEvaluatesToFalse() { assertThat(isInnerClass).rejects(InnerClassesTestCase.StaticNestedClass.class); } @Test void privateInnerClassEvaluatesToFalse() { assertThat(isInnerClass).rejects(InnerClassesTestCase.PrivateInnerClass.class); } private static class InnerClassesTestCase { class InnerClass { } static class StaticNestedClass { } private class PrivateInnerClass { } } } IsNestedTestClassTests.java000066400000000000000000000024011455764576500401430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; import java.util.function.Predicate; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; /** * @since 5.0 */ class IsNestedTestClassTests { private final Predicate> isNestedTestClass = new IsNestedTestClass(); @Test void innerClassEvaluatesToTrue() { assertThat(isNestedTestClass).accepts(NestedClassesTestCase.InnerClass.class); } @Test void staticNestedClassEvaluatesToFalse() { assertThat(isNestedTestClass).rejects(NestedClassesTestCase.StaticNestedClass.class); } @Test void privateNestedClassEvaluatesToFalse() { assertThat(isNestedTestClass).rejects(NestedClassesTestCase.PrivateInnerClass.class); } private static class NestedClassesTestCase { @Nested class InnerClass { } @Nested static class StaticNestedClass { } @Nested private class PrivateInnerClass { } } } IsPotentialTestContainerTests.java000066400000000000000000000027601455764576500415450ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * @since 5.0 */ class IsPotentialTestContainerTests { private final IsPotentialTestContainer isPotentialTestContainer = new IsPotentialTestContainer(); @Test void staticClassEvaluatesToTrue() { assertTrue(isPotentialTestContainer.test(StaticClass.class)); } @Test void privateStaticClassEvaluatesToFalse() { assertFalse(isPotentialTestContainer.test(PrivateStaticClass.class)); } @Test void abstractClassEvaluatesToFalse() { assertFalse(isPotentialTestContainer.test(AbstractClass.class)); } @Test void localClassEvaluatesToFalse() { class LocalClass { } assertFalse(isPotentialTestContainer.test(LocalClass.class)); } @Test void anonymousClassEvaluatesToFalse() { Object object = new Object() { @Override public String toString() { return ""; } }; assertFalse(isPotentialTestContainer.test(object.getClass())); } private static class PrivateStaticClass { } static class StaticClass { } } abstract class AbstractClass { } IsTestClassWithTestsTests.java000066400000000000000000000100501455764576500406560ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Collection; import java.util.function.Predicate; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; /** * Unit tests for {@link IsTestClassWithTests}. * * @since 5.0 */ class IsTestClassWithTestsTests { private final Predicate> isTestClassWithTests = new IsTestClassWithTests(); @Test void classWithTestMethodEvaluatesToTrue() { assertTrue(isTestClassWithTests.test(ClassWithTestMethod.class)); } @Test void classWithTestFactoryEvaluatesToTrue() { assertTrue(isTestClassWithTests.test(ClassWithTestFactory.class)); } @Test void classWithTestTemplateEvaluatesToTrue() { assertTrue(isTestClassWithTests.test(ClassWithTestTemplate.class)); } @Test void classWithNestedTestClassEvaluatesToTrue() { assertTrue(isTestClassWithTests.test(ClassWithNestedTestClass.class)); } @Test void staticTestClassEvaluatesToTrue() { assertTrue(isTestClassWithTests.test(StaticTestCase.class)); } // ------------------------------------------------------------------------- @Test void privateClassWithTestMethodEvaluatesToFalse() { assertFalse(isTestClassWithTests.test(PrivateClassWithTestMethod.class)); } @Test void privateClassWithTestFactoryEvaluatesToFalse() { assertFalse(isTestClassWithTests.test(PrivateClassWithTestFactory.class)); } @Test void privateClassWithTestTemplateEvaluatesToFalse() { assertFalse(isTestClassWithTests.test(PrivateClassWithTestTemplate.class)); } @Test void privateClassWithNestedTestCasesEvaluatesToFalse() { assertFalse(isTestClassWithTests.test(PrivateClassWithNestedTestClass.class)); } @Test void privateStaticTestClassEvaluatesToFalse() { assertFalse(isTestClassWithTests.test(PrivateStaticTestCase.class)); } /** * @see https://github.com/junit-team/junit5/issues/2249 */ @Test void recursiveHierarchies() { assertTrue(isTestClassWithTests.test(OuterClass.class)); assertFalse(isTestClassWithTests.test(OuterClass.RecursiveInnerClass.class)); } // ------------------------------------------------------------------------- private class PrivateClassWithTestMethod { @Test void test() { } } private class PrivateClassWithTestFactory { @TestFactory Collection factory() { return new ArrayList<>(); } } private class PrivateClassWithTestTemplate { @TestTemplate void template(int a) { } } private class PrivateClassWithNestedTestClass { @Nested class InnerClass { @Test void first() { } @Test void second() { } } } // ------------------------------------------------------------------------- static class StaticTestCase { @Test void test() { } } private static class PrivateStaticTestCase { @Test void test() { } } static class OuterClass { @Nested class InnerClass { @Test void test() { } } // Intentionally commented out so that RecursiveInnerClass is NOT a candidate test class // @Nested class RecursiveInnerClass extends OuterClass { } } } // ----------------------------------------------------------------------------- class ClassWithTestMethod { @Test void test() { } } class ClassWithTestFactory { @TestFactory Collection factory() { return new ArrayList<>(); } } class ClassWithTestTemplate { @TestTemplate void template(int a) { } } class ClassWithNestedTestClass { @Nested class InnerClass { @Test void first() { } @Test void second() { } } } IsTestFactoryMethodTests.java000066400000000000000000000044341455764576500405130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.function.Predicate; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link IsTestFactoryMethod}. * * @since 5.0 */ class IsTestFactoryMethodTests { private static final Predicate isTestFactoryMethod = new IsTestFactoryMethod(); @Test void factoryMethodReturningCollectionOfDynamicTests() { assertThat(isTestFactoryMethod).accepts(method("dynamicTestsFactory")); } @Test void bogusFactoryMethodReturningVoid() { assertThat(isTestFactoryMethod).rejects(method("bogusVoidFactory")); } // TODO [#949] Enable test once IsTestFactoryMethod properly checks return type. @Disabled("Disabled until IsTestFactoryMethod properly checks return type") @Test void bogusFactoryMethodReturningObject() { assertThat(isTestFactoryMethod).rejects(method("bogusObjectFactory")); } // TODO [#949] Enable test once IsTestFactoryMethod properly checks return type. @Disabled("Disabled until IsTestFactoryMethod properly checks return type") @Test void bogusFactoryMethodReturningCollectionOfStrings() { assertThat(isTestFactoryMethod).rejects(method("bogusStringsFactory")); } private static Method method(String name) { return ReflectionUtils.findMethod(ClassWithTestFactoryMethods.class, name).get(); } private static class ClassWithTestFactoryMethods { @TestFactory Collection dynamicTestsFactory() { return new ArrayList<>(); } @TestFactory void bogusVoidFactory() { } @TestFactory Object bogusObjectFactory() { return new Object(); } @TestFactory Collection bogusStringsFactory() { return new ArrayList<>(); } } } IsTestMethodTests.java000066400000000000000000000065601455764576500371650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Method; import java.util.function.Predicate; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link IsTestMethod}. * * @since 5.0 */ class IsTestMethodTests { private static final Predicate isTestMethod = new IsTestMethod(); @Test void publicTestMethod() { Method method = method("publicTestMethod"); // Ensure that somebody doesn't accidentally delete the public modifier again. assertTrue(ReflectionUtils.isPublic(method)); assertThat(isTestMethod).accepts(method); } @Test void publicTestMethodWithArgument() { Method method = method("publicTestMethodWithArgument", TestInfo.class); // Ensure that somebody doesn't accidentally delete the public modifier again. assertTrue(ReflectionUtils.isPublic(method)); assertThat(isTestMethod).accepts(method); } @Test void protectedTestMethod() { assertThat(isTestMethod).accepts(method("protectedTestMethod")); } @Test void packageVisibleTestMethod() { assertThat(isTestMethod).accepts(method("packageVisibleTestMethod")); } @Test void bogusAbstractTestMethod() { assertThat(isTestMethod).rejects(abstractMethod("bogusAbstractTestMethod")); } @Test void bogusStaticTestMethod() { assertThat(isTestMethod).rejects(method("bogusStaticTestMethod")); } @Test void bogusPrivateTestMethod() { assertThat(isTestMethod).rejects(method("bogusPrivateTestMethod")); } @Test void bogusTestMethodReturningObject() { assertThat(isTestMethod).rejects(method("bogusTestMethodReturningObject")); } @Test void bogusTestMethodReturningVoidReference() { assertThat(isTestMethod).rejects(method("bogusTestMethodReturningVoidReference")); } @Test void bogusTestMethodReturningPrimitive() { assertThat(isTestMethod).rejects(method("bogusTestMethodReturningPrimitive")); } private static Method method(String name, Class... parameterTypes) { return ReflectionUtils.findMethod(ClassWithTestMethods.class, name, parameterTypes).get(); } private Method abstractMethod(String name) { return ReflectionUtils.findMethod(AbstractClassWithAbstractTestMethod.class, name).get(); } private static abstract class AbstractClassWithAbstractTestMethod { @Test abstract void bogusAbstractTestMethod(); } private static class ClassWithTestMethods { @Test static void bogusStaticTestMethod() { } @Test private void bogusPrivateTestMethod() { } @Test String bogusTestMethodReturningObject() { return ""; } @Test Void bogusTestMethodReturningVoidReference() { return null; } @Test int bogusTestMethodReturningPrimitive() { return 0; } @Test public void publicTestMethod() { } @Test public void publicTestMethodWithArgument(TestInfo info) { } @Test protected void protectedTestMethod() { } @Test void packageVisibleTestMethod() { } } } IsTestTemplateMethodTests.java000066400000000000000000000025711455764576500406570ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/discovery/predicates/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Method; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestTemplate; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link IsTestTemplateMethod}. * * @since 5.0 */ class IsTestTemplateMethodTests { private static final IsTestTemplateMethod isTestTemplateMethod = new IsTestTemplateMethod(); @Test void testTemplateMethodReturningVoid() { assertThat(isTestTemplateMethod).accepts(method("templateReturningVoid")); } @Test void bogusTestTemplateMethodReturningObject() { assertThat(isTestTemplateMethod).rejects(method("bogusTemplateReturningObject")); } private static Method method(String name) { return ReflectionUtils.findMethod(ClassWithTestTemplateMethods.class, name).get(); } private static class ClassWithTestTemplateMethods { @TestTemplate void templateReturningVoid() { } @TestTemplate String bogusTemplateReturningObject() { return ""; } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/000077500000000000000000000000001455764576500306445ustar00rootroot00000000000000AbstractExecutableInvokerTests.java000066400000000000000000000071661455764576500375700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConfigurableParameterResolver; import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConstructorInjectionTestCase; import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.MethodSource; import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.NumberParameterResolver; import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.StringParameterResolver; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.9 */ abstract class AbstractExecutableInvokerTests { private static final String ENIGMA = "enigma"; protected final MethodSource instance = mock(); protected Method method; protected final ExtensionContext extensionContext = mock(); private final JupiterConfiguration configuration = mock(); protected final MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions( configuration); @Test void constructorInjection() { register(new StringParameterResolver(), new NumberParameterResolver()); Class outerClass = ConstructorInjectionTestCase.class; Constructor constructor = ReflectionUtils.getDeclaredConstructor(outerClass); ConstructorInjectionTestCase outer = invokeConstructor(constructor, null); assertNotNull(outer); assertEquals(ENIGMA, outer.str); Class innerClass = ConstructorInjectionTestCase.NestedTestCase.class; Constructor innerConstructor = ReflectionUtils.getDeclaredConstructor( innerClass); ConstructorInjectionTestCase.NestedTestCase inner = invokeConstructor(innerConstructor, outer); assertNotNull(inner); assertEquals(42, inner.num); } @Test void resolveArgumentsViaParameterResolver() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("argument"); invokeMethod(); verify(instance).singleStringParameter("argument"); } private void thereIsAParameterResolverThatResolvesTheParameterTo(Object argument) { register(ConfigurableParameterResolver.supportsAndResolvesTo(parameterContext -> argument)); } private void testMethodWithASingleStringParameter() { this.method = ReflectionUtils.findMethod(this.instance.getClass(), "singleStringParameter", String.class).get(); } private void register(ParameterResolver... resolvers) { for (ParameterResolver resolver : resolvers) { extensionRegistry.registerExtension(resolver, this); } } abstract void invokeMethod(); abstract T invokeConstructor(Constructor constructor, Object outerInstance); } DefaultExecutableInvokerTests.java000066400000000000000000000016461455764576500374060ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import java.lang.reflect.Constructor; /** * Unit tests for {@link DefaultExecutableInvoker}. * * @since 5.9 */ class DefaultExecutableInvokerTests extends AbstractExecutableInvokerTests { @Override void invokeMethod() { newInvoker().invoke(this.method, this.instance); } @Override T invokeConstructor(Constructor constructor, Object outerInstance) { return newInvoker().invoke(constructor, outerInstance); } private DefaultExecutableInvoker newInvoker() { return new DefaultExecutableInvoker(this.extensionContext, this.extensionRegistry); } } DefaultTestInstancesTests.java000066400000000000000000000032171455764576500365520ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; class DefaultTestInstancesTests { @Test void topLevelClass() { DefaultTestInstances instances = DefaultTestInstances.of(this); assertThat(instances.getInnermostInstance()).isSameAs(this); assertThat(instances.getAllInstances()).containsExactly(this); assertThat(instances.getEnclosingInstances()).isEmpty(); assertThat(instances.findInstance(Object.class)).contains(this); assertThat(instances.findInstance(String.class)).isEmpty(); } @Test void nestedLevelClass() { DefaultTestInstancesTests outermost = this; Nested innermost = new Nested(); DefaultTestInstances instances = DefaultTestInstances.of(DefaultTestInstances.of(outermost), innermost); assertThat(instances.getInnermostInstance()).isSameAs(innermost); assertThat(instances.getAllInstances()).containsExactly(outermost, innermost); assertThat(instances.getEnclosingInstances()).containsExactly(outermost); assertThat(instances.findInstance(Object.class)).contains(innermost); assertThat(instances.findInstance(Nested.class)).contains(innermost); assertThat(instances.findInstance(DefaultTestInstancesTests.class)).contains(outermost); assertThat(instances.findInstance(String.class)).isEmpty(); } class Nested { } } DynamicTestIntegrationTests.java000066400000000000000000000025761455764576500371150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; /** * Integration tests for dynamic tests. * * @since 5.5 */ class DynamicTestIntegrationTests { private static final int TEN_MB = 10 * 1024 * 1024; /** * Without the fix in {@code DynamicTestTestDescriptor}, setting the * {@code -mx200m} VM argument will cause an {@link OutOfMemoryError} before * the 200 limit is reached. * * @see Issue 1865 */ @TestFactory Stream generateDynamicTestsThatReferenceLargeAmountsOfMemory() { return Stream.generate(() -> new byte[TEN_MB])// // The lambda Executable in the following line *must* reference // the `bytes` array in order to hold onto the allocated memory. .map(bytes -> dynamicTest("test", () -> assertNotNull(bytes)))// .limit(200); } } ExtensionContextStoreConcurrencyTests.java000066400000000000000000000032051455764576500412240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; /** * Concurrency tests for {@link NamespaceAwareStore} and {@link NamespacedHierarchicalStore}. * * @since 5.0 */ class ExtensionContextStoreConcurrencyTests { private final AtomicInteger count = new AtomicInteger(); @Test void concurrentAccessToDefaultStoreWithoutParentStore() { // Run the actual test 100 times "for good measure". IntStream.range(1, 100).forEach(i -> { Store store = reset(); // Simulate 100 extensions interacting concurrently with the Store. IntStream.range(1, 100).parallel().forEach(j -> store.getOrComputeIfAbsent("key", this::newValue)); assertEquals(1, count.get(), () -> "number of times newValue() was invoked in run #" + i); }); } private String newValue(String key) { count.incrementAndGet(); return "value"; } private Store reset() { count.set(0); return new NamespaceAwareStore(new NamespacedHierarchicalStore<>(null), Namespace.GLOBAL); } } ExtensionContextStoreTests.java000066400000000000000000000064011455764576500370120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ExtensionContextException; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; import org.junit.platform.engine.support.store.NamespacedHierarchicalStoreException; /** * Unit tests for {@link NamespaceAwareStore} and {@link NamespacedHierarchicalStore}. * * @since 5.5 * @see ExtensionContextStoreConcurrencyTests * @see ExtensionValuesStoreTests */ class ExtensionContextStoreTests { private static final String KEY = "key"; private static final String VALUE = "value"; private final NamespacedHierarchicalStore parentStore = new NamespacedHierarchicalStore<>(null); private final NamespacedHierarchicalStore localStore = new NamespacedHierarchicalStore<>(parentStore); private final Store store = new NamespaceAwareStore(localStore, Namespace.GLOBAL); @Test void getOrDefaultWithNoValuePresent() { assertThat(store.get(KEY)).isNull(); assertThat(store.getOrDefault(KEY, boolean.class, true)).isTrue(); assertThat(store.getOrDefault(KEY, String.class, VALUE)).isEqualTo(VALUE); } @Test void getOrDefaultRequestingIncompatibleType() { localStore.put(Namespace.GLOBAL, KEY, VALUE); assertThat(store.get(KEY)).isEqualTo(VALUE); Exception exception = assertThrows(ExtensionContextException.class, () -> store.getOrDefault(KEY, boolean.class, true)); assertThat(exception) // .hasMessageContaining("is not of required type") // .hasCauseInstanceOf(NamespacedHierarchicalStoreException.class) // .hasStackTraceContaining(NamespacedHierarchicalStore.class.getName()); } @Test void getOrDefaultWithValueInLocalStore() { localStore.put(Namespace.GLOBAL, KEY, VALUE); assertThat(store.get(KEY)).isEqualTo(VALUE); assertThat(store.getOrDefault(KEY, String.class, VALUE)).isEqualTo(VALUE); } @Test void getOrDefaultWithValueInParentStore() { parentStore.put(Namespace.GLOBAL, KEY, VALUE); assertThat(store.get(KEY)).isEqualTo(VALUE); assertThat(store.getOrDefault(KEY, String.class, VALUE)).isEqualTo(VALUE); } @Test void getOrComputeIfAbsentWithFailingCreator() { var invocations = new AtomicInteger(); var e1 = assertThrows(RuntimeException.class, () -> store.getOrComputeIfAbsent(KEY, __ -> { invocations.incrementAndGet(); throw new RuntimeException(); })); var e2 = assertThrows(RuntimeException.class, () -> store.get(KEY)); assertSame(e1, e2); assertDoesNotThrow(localStore::close); assertThat(invocations).hasValue(1); } } InterceptingExecutableInvokerTests.java000066400000000000000000000026361455764576500404550ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.util.Optional; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; /** * Unit tests for {@link InterceptingExecutableInvoker}. * * @since 5.0 */ class InterceptingExecutableInvokerTests extends AbstractExecutableInvokerTests { @Override void invokeMethod() { newInvoker().invoke(this.method, this.instance, this.extensionContext, this.extensionRegistry, passthroughInterceptor()); } @Override T invokeConstructor(Constructor constructor, Object outerInstance) { return newInvoker().invoke(constructor, Optional.ofNullable(outerInstance), extensionContext, extensionRegistry, passthroughInterceptor()); } private InterceptingExecutableInvoker newInvoker() { return new InterceptingExecutableInvoker(); } private static ReflectiveInterceptorCall passthroughInterceptor() { return (interceptor, invocation, invocationContext, extensionContext) -> invocation.proceed(); } } JupiterEngineExecutionContextTests.java000066400000000000000000000104311455764576500404530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.EngineExecutionListener; /** * Unit tests for {@link JupiterEngineExecutionContext}. * * @since 5.0 */ class JupiterEngineExecutionContextTests { private final JupiterConfiguration configuration = mock(); private final EngineExecutionListener engineExecutionListener = mock(); private final JupiterEngineExecutionContext originalContext = new JupiterEngineExecutionContext( engineExecutionListener, configuration); @Test void executionListenerIsHandedOnWhenContextIsExtended() { assertSame(engineExecutionListener, originalContext.getExecutionListener()); JupiterEngineExecutionContext newContext = originalContext.extend().build(); assertSame(engineExecutionListener, newContext.getExecutionListener()); } @Test void extendWithAllAttributes() { ExtensionContext extensionContext = mock(); MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions( configuration); TestInstancesProvider testInstancesProvider = mock(); JupiterEngineExecutionContext newContext = originalContext.extend() // .withExtensionContext(extensionContext) // .withExtensionRegistry(extensionRegistry) // .withTestInstancesProvider(testInstancesProvider) // .build(); assertSame(extensionContext, newContext.getExtensionContext()); assertSame(extensionRegistry, newContext.getExtensionRegistry()); assertSame(testInstancesProvider, newContext.getTestInstancesProvider()); } @Test void canOverrideAttributeWhenContextIsExtended() { ExtensionContext extensionContext = mock(); MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions( configuration); TestInstancesProvider testInstancesProvider = mock(); ExtensionContext newExtensionContext = mock(); JupiterEngineExecutionContext newContext = originalContext.extend() // .withExtensionContext(extensionContext) // .withExtensionRegistry(extensionRegistry) // .withTestInstancesProvider(testInstancesProvider) // .build() // .extend() // .withExtensionContext(newExtensionContext) // .build(); assertSame(newExtensionContext, newContext.getExtensionContext()); assertSame(extensionRegistry, newContext.getExtensionRegistry()); assertSame(testInstancesProvider, newContext.getTestInstancesProvider()); } @Test @TrackLogRecords void closeAttemptExceptionWillBeThrownDownTheCallStack(LogRecordListener logRecordListener) throws Exception { ExtensionContext failingExtensionContext = mock(ExtensionContext.class, withSettings().extraInterfaces(AutoCloseable.class)); Exception expectedException = new Exception("test message"); doThrow(expectedException).when(((AutoCloseable) failingExtensionContext)).close(); JupiterEngineExecutionContext newContext = originalContext.extend() // .withExtensionContext(failingExtensionContext) // .build(); Exception actualException = assertThrows(Exception.class, newContext::close); assertSame(expectedException, actualException); assertThat(logRecordListener.stream(JupiterEngineExecutionContext.class, Level.SEVERE)) // .extracting(LogRecord::getMessage) // .containsOnly("Caught exception while closing extension context: " + failingExtensionContext); } } ParameterResolutionUtilsTests.java000066400000000000000000000365471455764576500375170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link ParameterResolutionUtils}. * * @since 5.9 */ class ParameterResolutionUtilsTests { private static final String ENIGMA = "enigma"; private final MethodSource instance = mock(); private Method method; private final ExtensionContext extensionContext = mock(); private final JupiterConfiguration configuration = mock(); private final MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry.createRegistryWithDefaultExtensions( configuration); @Test void resolveConstructorArguments() { register(new StringParameterResolver()); Class topLevelClass = ConstructorInjectionTestCase.class; Object[] arguments = resolveConstructorParameters(topLevelClass, null); assertThat(arguments).containsExactly(ENIGMA); } @Test void resolveNestedConstructorArguments() { register(new NumberParameterResolver()); Class outerClass = ConstructorInjectionTestCase.class; ConstructorInjectionTestCase outer = ReflectionUtils.newInstance(outerClass, "str"); Class innerClass = ConstructorInjectionTestCase.NestedTestCase.class; Object[] arguments = resolveConstructorParameters(innerClass, outer); assertThat(arguments).containsExactly(outer, 42); } @Test void resolveConstructorArgumentsWithMissingResolver() { Constructor constructor = ReflectionUtils.getDeclaredConstructor( ConstructorInjectionTestCase.class); Exception exception = assertThrows(ParameterResolutionException.class, () -> ParameterResolutionUtils.resolveParameters(constructor, Optional.empty(), Optional.empty(), extensionContext, extensionRegistry)); assertThat(exception.getMessage())// .contains("No ParameterResolver registered for parameter [java.lang.String")// .contains("in constructor")// .contains(ConstructorInjectionTestCase.class.getName()); } @Test void resolvingArgumentsForMethodsWithoutParameterDoesNotDependOnParameterResolvers() { testMethodWithNoParameters(); throwDuringParameterResolution(new RuntimeException("boom!")); Object[] arguments = resolveMethodParameters(); assertThat(arguments).isEmpty(); } @Test void resolveArgumentsViaParameterResolver() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("argument"); Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("argument"); } @Test void resolveMultipleArguments() { testMethodWith("multipleParameters", String.class, Integer.class, Double.class); register(ConfigurableParameterResolver.supportsAndResolvesTo(parameterContext -> { switch (parameterContext.getIndex()) { case 0: return "0"; case 1: return 1; default: return 2.0; } })); Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("0", 1, 2.0); } @Test void onlyConsiderParameterResolversThatSupportAParticularParameter() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatDoesNotSupportThisParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("something"); Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("something"); } @Test void passContextInformationToParameterResolverMethods() { anyTestMethodWithAtLeastOneParameter(); ArgumentRecordingParameterResolver extension = new ArgumentRecordingParameterResolver(); register(extension); resolveMethodParameters(); assertSame(extensionContext, extension.supportsArguments.extensionContext); assertEquals(0, extension.supportsArguments.parameterContext.getIndex()); assertSame(instance, extension.supportsArguments.parameterContext.getTarget().get()); assertSame(extensionContext, extension.resolveArguments.extensionContext); assertEquals(0, extension.resolveArguments.parameterContext.getIndex()); assertSame(instance, extension.resolveArguments.parameterContext.getTarget().get()); assertThat(extension.resolveArguments.parameterContext.toString())// .contains("parameter", String.class.getTypeName(), "index", "0", "target", "Mock"); } @Test void resolvingArgumentsForMethodsWithPrimitiveTypesIsSupported() { testMethodWithASinglePrimitiveIntParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(42); Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly(42); } @Test void nullIsAViableArgumentIfAReferenceTypeParameterIsExpected() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(null); Object[] arguments = resolveMethodParameters(); assertThat(arguments).hasSize(1); assertNull(arguments[0]); } @Test void reportThatNullIsNotAViableArgumentIfAPrimitiveTypeIsExpected() { testMethodWithASinglePrimitiveIntParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(null); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); // @formatter:off assertThat(caught.getMessage()) .contains("in method") .contains("resolved a null value for parameter [int") .contains("but a primitive of type [int] is required."); // @formatter:on } @Test void reportIfThereIsNoParameterResolverThatSupportsTheParameter() { testMethodWithASingleStringParameter(); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); assertThat(caught.getMessage()).contains("parameter [java.lang.String").contains("in method"); } @Test void reportIfThereAreMultipleParameterResolversThatSupportTheParameter() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("one"); thereIsAParameterResolverThatResolvesTheParameterTo("two"); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); String className = Pattern.quote(ConfigurableParameterResolver.class.getName()); // @formatter:off assertThat(caught.getMessage()) .matches("Discovered multiple competing ParameterResolvers for parameter \\[java.lang.String .+?\\] " + "in method .+: " + className + "@.+, " + className + "@.+"); // @formatter:on } @Test void reportTypeMismatchBetweenParameterAndResolvedParameter() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(BigDecimal.ONE); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); // @formatter:off assertThat(caught.getMessage()) .contains("resolved a value of type [java.math.BigDecimal] for parameter [java.lang.String") .contains("in method") .contains("but a value assignment compatible with [java.lang.String] is required."); // @formatter:on } @Test void wrapAllExceptionsThrownDuringParameterResolutionIntoAParameterResolutionException() { anyTestMethodWithAtLeastOneParameter(); IllegalArgumentException cause = anyExceptionButParameterResolutionException(); throwDuringParameterResolution(cause); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); assertSame(cause, caught.getCause(), () -> "cause should be present"); assertThat(caught.getMessage())// .matches("^Failed to resolve parameter \\[java.lang.String .+?\\] in method \\[.+?\\]$"); } @Test void exceptionMessageContainsMessageFromExceptionThrownDuringParameterResolution() { anyTestMethodWithAtLeastOneParameter(); RuntimeException cause = new RuntimeException("boom!"); throwDuringParameterResolution(cause); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); assertSame(cause, caught.getCause(), () -> "cause should be present"); assertThat(caught.getMessage())// .matches("^Failed to resolve parameter \\[java.lang.String .+?\\] in method \\[.+?\\]: boom!$"); } @Test void doNotWrapThrownExceptionIfItIsAlreadyAParameterResolutionException() { anyTestMethodWithAtLeastOneParameter(); ParameterResolutionException cause = new ParameterResolutionException("custom message"); throwDuringParameterResolution(cause); ParameterResolutionException caught = assertThrows(ParameterResolutionException.class, this::resolveMethodParameters); assertSame(cause, caught); } private IllegalArgumentException anyExceptionButParameterResolutionException() { return new IllegalArgumentException(); } private void throwDuringParameterResolution(RuntimeException parameterResolutionException) { register(ConfigurableParameterResolver.onAnyCallThrow(parameterResolutionException)); } private void thereIsAParameterResolverThatResolvesTheParameterTo(Object argument) { register(ConfigurableParameterResolver.supportsAndResolvesTo(parameterContext -> argument)); } private void thereIsAParameterResolverThatDoesNotSupportThisParameter() { register(ConfigurableParameterResolver.withoutSupport()); } private void anyTestMethodWithAtLeastOneParameter() { testMethodWithASingleStringParameter(); } private void testMethodWithNoParameters() { testMethodWith("noParameter"); } private void testMethodWithASingleStringParameter() { testMethodWith("singleStringParameter", String.class); } private void testMethodWithASinglePrimitiveIntParameter() { testMethodWith("primitiveParameterInt", int.class); } private void testMethodWith(String methodName, Class... parameterTypes) { this.method = ReflectionUtils.findMethod(this.instance.getClass(), methodName, parameterTypes).get(); } private void register(ParameterResolver... resolvers) { for (ParameterResolver resolver : resolvers) { extensionRegistry.registerExtension(resolver, this); } } private Object[] resolveConstructorParameters(Class clazz, Object outerInstance) { Constructor constructor = ReflectionUtils.getDeclaredConstructor(clazz); return ParameterResolutionUtils.resolveParameters(constructor, Optional.empty(), Optional.ofNullable(outerInstance), extensionContext, extensionRegistry); } private Object[] resolveMethodParameters() { return ParameterResolutionUtils.resolveParameters(this.method, Optional.of(this.instance), this.extensionContext, this.extensionRegistry); } // ------------------------------------------------------------------------- static class ArgumentRecordingParameterResolver implements ParameterResolver { ArgumentRecordingParameterResolver.Arguments supportsArguments; ArgumentRecordingParameterResolver.Arguments resolveArguments; static class Arguments { final ParameterContext parameterContext; final ExtensionContext extensionContext; Arguments(ParameterContext parameterContext, ExtensionContext extensionContext) { this.parameterContext = parameterContext; this.extensionContext = extensionContext; } } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { supportsArguments = new ArgumentRecordingParameterResolver.Arguments(parameterContext, extensionContext); return true; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { resolveArguments = new ArgumentRecordingParameterResolver.Arguments(parameterContext, extensionContext); return null; } } static class ConfigurableParameterResolver implements ParameterResolver { static ParameterResolver onAnyCallThrow(RuntimeException runtimeException) { return new ConfigurableParameterResolver(parameterContext -> { throw runtimeException; }, parameterContext -> { throw runtimeException; }); } static ParameterResolver supportsAndResolvesTo(Function resolve) { return new ConfigurableParameterResolver(parameterContext -> true, resolve); } static ParameterResolver withoutSupport() { return new ConfigurableParameterResolver(parameterContext -> false, parameter -> { throw new UnsupportedOperationException(); }); } private final Predicate supports; private final Function resolve; private ConfigurableParameterResolver(Predicate supports, Function resolve) { this.supports = supports; this.resolve = resolve; } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return supports.test(parameterContext); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return resolve.apply(parameterContext); } } @SuppressWarnings("unused") interface MethodSource { void noParameter(); void singleStringParameter(String parameter); void primitiveParameterInt(int parameter); void multipleParameters(String first, Integer second, Double third); } static class StringParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == String.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return ENIGMA; } } static class NumberParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == Number.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return 42; } } static class ConstructorInjectionTestCase { final String str; @SuppressWarnings("unused") ConstructorInjectionTestCase(String str) { this.str = str; } class NestedTestCase { final Number num; @SuppressWarnings("unused") NestedTestCase(Number num) { this.num = num; } } } } UniqueIdParsingForArrayParameterIntegrationTests.java000066400000000000000000000044211455764576500432360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.execution.injection.sample.PrimitiveArrayParameterResolver; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Event; /** * Integration tests for {@link UniqueId#parse(String)} for methods * with array type parameters. * * @see #810 * @see org.junit.platform.engine.UniqueIdTests * * @since 5.0 */ class UniqueIdParsingForArrayParameterIntegrationTests extends AbstractJupiterTestEngineTests { @Test void executeTestsForPrimitiveArrayMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass(PrimitiveArrayMethodInjectionTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off UniqueId uniqueId = executionResults.allEvents() .map(Event::getTestDescriptor) .distinct() .skip(2) .map(TestDescriptor::getUniqueId) .findFirst() .orElseThrow(AssertionError::new); // @formatter:on assertThat(UniqueId.parse(uniqueId.toString())).isEqualTo(uniqueId); } @ExtendWith(PrimitiveArrayParameterResolver.class) static class PrimitiveArrayMethodInjectionTestCase { @Test void primitiveArray(int... ints) { assertArrayEquals(new int[] { 1, 2, 3 }, ints); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/000077500000000000000000000000001455764576500326265ustar00rootroot00000000000000sample/000077500000000000000000000000001455764576500340305ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injectionCustomAnnotation.java000066400000000000000000000012331455764576500401770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @since 5.0 */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CustomAnnotation { } CustomAnnotationParameterResolver.java000066400000000000000000000024141455764576500435640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ public class CustomAnnotationParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { // We invoke parameterContext.isAnnotated() instead of parameterContext.getParameter().isAnnotationPresent() // in order to verify support for the convenience method in the ParameterContext API. return parameterContext.isAnnotated(CustomAnnotation.class); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return ReflectionUtils.newInstance(parameterContext.getParameter().getType()); } } CustomType.java000066400000000000000000000010741455764576500370110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import java.util.Date; /** * @since 5.0 */ public class CustomType { private final Date date = new Date(); @Override public String toString() { return "CustomType: " + this.date; } } CustomTypeParameterResolver.java000066400000000000000000000017371455764576500424020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * @since 5.0 */ public class CustomTypeParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType().equals(CustomType.class); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return new CustomType(); } } DoubleParameterResolver.java000066400000000000000000000020621455764576500414700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that always resolves a {@link Double} * parameter to {@code 42.0}. * * @since 5.0 */ public class DoubleParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == Double.class; } @Override public Double resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return 42.0; } } LongParameterResolver.java000066400000000000000000000040111455764576500411510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that always resolves a {@link Long} * parameter to {@code 42}. * *

This resolver also attempts to support generic parameter type * declarations if the generic type is defined at the class level in a * superclass or interface (extended or implemented by the test class) and * is assignable from {@link Long}. * * @since 5.0 */ public class LongParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { // Exact match? if (parameterContext.getParameter().getType() == Long.class) { return true; } Type typeInMethod = parameterContext.getParameter().getParameterizedType(); // Type variables in parameterized class for (TypeVariable typeVariable : parameterContext.getDeclaringExecutable().getDeclaringClass().getTypeParameters()) { boolean namesMatch = typeInMethod.getTypeName().equals(typeVariable.getName()); boolean typesAreCompatible = typeVariable.getBounds().length == 1 && // typeVariable.getBounds()[0] instanceof Class && // ((Class) typeVariable.getBounds()[0]).isAssignableFrom(Long.class); if (namesMatch && typesAreCompatible) { return true; } } return false; } @Override public Long resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return 42L; } } MapOfListsTypeBasedParameterResolver.java000066400000000000000000000016501455764576500441020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import java.util.List; import java.util.Map; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.support.TypeBasedParameterResolver; /** * @since 5.6 */ public class MapOfListsTypeBasedParameterResolver extends TypeBasedParameterResolver>> { @Override public Map> resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return Map.of("ids", List.of(1, 42)); } } MapOfStringsParameterResolver.java000066400000000000000000000030321455764576500426300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; import java.util.TreeMap; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that resolves {@code Map} types. * * @since 5.0 */ public class MapOfStringsParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Type type = parameterContext.getParameter().getParameterizedType(); if (!(type instanceof ParameterizedType)) { return false; } Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); if (actualTypeArguments.length != 2) { return false; } return actualTypeArguments[0] == String.class && actualTypeArguments[1] == String.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Map map = new TreeMap<>(); map.put("key", "value"); return map; } } NullIntegerParameterResolver.java000066400000000000000000000022171455764576500425100ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that always resolves an * {@link Integer} or {@code int} parameter to a {@code null} value. * * @since 5.0 */ public class NullIntegerParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return Integer.class == parameterContext.getParameter().getType() || int.class == parameterContext.getParameter().getType(); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return null; } } NumberParameterResolver.java000066400000000000000000000040001455764576500415000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * This is a non-realistic {@link ParameterResolver} that claims to * resolve any {@link Number}, when in fact it always resolves an {@link Integer}. * *

This may appear nonsensical; however, there are use cases for which a * resolver may think that it can support a particular parameter only to * discover later that the actual resolved value is not assignment compatible. * *

For example, consider the case with Spring: the {@code SpringExtension} can * theoretically resolve any type of {@code ApplicationContext}, but if the * required parameter type is {@code WebApplicationContext} and the user * neglects to annotate the test class with {@code @WebAppConfiguration} then * the {@code ApplicationContext} loaded by Spring's testing support will in * fact be an {@code ApplicationContext} but not a {@code WebApplicationContext}. * Since Spring does not determine this in advance, such a scenario would lead to * an {@link IllegalArgumentException} with the message "argument type mismatch" * when JUnit attempts to invoke the test method. * * @since 5.0 */ public class NumberParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return Number.class.isAssignableFrom(parameterContext.getParameter().getType()); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return 42; } } PrimitiveArrayParameterResolver.java000066400000000000000000000020621455764576500432250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that resolves arrays of primitive integers. * * @since 5.0 */ public class PrimitiveArrayParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return int[].class == parameterContext.getParameter().getType(); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return new int[] { 1, 2, 3 }; } } PrimitiveIntegerParameterResolver.java000066400000000000000000000020251455764576500435430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/execution/injection/sample/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.execution.injection.sample; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; /** * Example {@link ParameterResolver} that resolves primitive integers. * * @since 5.0 */ public class PrimitiveIntegerParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return int.class == parameterContext.getParameter().getType(); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return 42; } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/000077500000000000000000000000001455764576500306555ustar00rootroot00000000000000BeforeAndAfterAllTests.java000066400000000000000000000231631455764576500357310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; /** * Integration tests that verify support for {@link BeforeAll}, {@link AfterAll}, * {@link BeforeAllCallback}, and {@link AfterAllCallback} in the {@link JupiterTestEngine}. * * @since 5.0 */ class BeforeAndAfterAllTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); private static Optional actualExceptionInAfterAllCallback; @Test void beforeAllAndAfterAllCallbacks() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(TopLevelTestCase.class, "fooBeforeAllCallback", "barBeforeAllCallback", "beforeAllMethod-1", "test-1", "afterAllMethod-1", "barAfterAllCallback", "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).isEmpty(); } @Test void beforeAllAndAfterAllCallbacksInSubclass() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(SecondLevelTestCase.class, "fooBeforeAllCallback", "barBeforeAllCallback", "bazBeforeAllCallback", "beforeAllMethod-1", "beforeAllMethod-2", "test-2", "afterAllMethod-2", "afterAllMethod-1", "bazAfterAllCallback", "barAfterAllCallback", "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).isEmpty(); } @Test void beforeAllAndAfterAllCallbacksInSubSubclass() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(ThirdLevelTestCase.class, "fooBeforeAllCallback", "barBeforeAllCallback", "bazBeforeAllCallback", "quuxBeforeAllCallback", "beforeAllMethod-1", "beforeAllMethod-2", "beforeAllMethod-3", "test-3", "afterAllMethod-3", "afterAllMethod-2", "afterAllMethod-1", "quuxAfterAllCallback", "bazAfterAllCallback", "barAfterAllCallback", "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).isEmpty(); } @Test void beforeAllAndAfterAllCallbacksInSubSubclassWithStaticMethodHiding() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(ThirdLevelStaticHidingTestCase.class, "fooBeforeAllCallback", "barBeforeAllCallback", "bazBeforeAllCallback", "quuxBeforeAllCallback", "beforeAllMethod-1-hidden", "beforeAllMethod-2-hidden", "beforeAllMethod-3", "test-3", // The @AfterAll methods are executed as 1/2/3 due to // the "stable" method sort order on the Platform. "afterAllMethod-1-hidden", "afterAllMethod-2-hidden", "afterAllMethod-3", "quuxAfterAllCallback", "bazAfterAllCallback", "barAfterAllCallback", "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).isEmpty(); } @Test void beforeAllMethodThrowsAnException() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(ExceptionInBeforeAllMethodTestCase.class, 0, 0, "fooBeforeAllCallback", "beforeAllMethod", // throws an exception. // test should not get invoked. "afterAllMethod", "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).containsInstanceOf(EnigmaException.class); } @Test void beforeAllCallbackThrowsAnException() { // @formatter:off assertBeforeAllAndAfterAllCallbacks(ExceptionInBeforeAllCallbackTestCase.class, 0, 0, "fooBeforeAllCallback", "exceptionThrowingBeforeAllCallback", // throws an exception. // beforeAllMethod should not get invoked. // test should not get invoked. // afterAllMethod should not get invoked. "fooAfterAllCallback" ); // @formatter:on assertThat(actualExceptionInAfterAllCallback).containsInstanceOf(EnigmaException.class); } private void assertBeforeAllAndAfterAllCallbacks(Class testClass, String... expectedCalls) { assertBeforeAllAndAfterAllCallbacks(testClass, 1, 1, expectedCalls); } private void assertBeforeAllAndAfterAllCallbacks(Class testClass, int testsStarted, int testsSuccessful, String... expectedCalls) { callSequence.clear(); executeTestsForClass(testClass).testEvents()// .assertStatistics(stats -> stats.started(testsStarted).succeeded(testsSuccessful)); assertEquals(asList(expectedCalls), callSequence, () -> "wrong call sequence for " + testClass.getName()); } // ------------------------------------------------------------------------- // Must NOT be private; otherwise, the @Test method gets discovered but never executed. @ExtendWith({ FooClassLevelCallbacks.class, BarClassLevelCallbacks.class }) static class TopLevelTestCase { @BeforeAll static void beforeAll1() { callSequence.add("beforeAllMethod-1"); } @AfterAll static void afterAll1() { callSequence.add("afterAllMethod-1"); } @Test void test() { callSequence.add("test-1"); } } // Must NOT be private; otherwise, the @Test method gets discovered but never executed. @ExtendWith(BazClassLevelCallbacks.class) static class SecondLevelTestCase extends TopLevelTestCase { @BeforeAll static void beforeAll2() { callSequence.add("beforeAllMethod-2"); } @AfterAll static void afterAll2() { callSequence.add("afterAllMethod-2"); } @Test @Override void test() { callSequence.add("test-2"); } } @ExtendWith(QuuxClassLevelCallbacks.class) static class ThirdLevelTestCase extends SecondLevelTestCase { @BeforeAll static void beforeAll3() { callSequence.add("beforeAllMethod-3"); } @AfterAll static void afterAll3() { callSequence.add("afterAllMethod-3"); } @Test @Override void test() { callSequence.add("test-3"); } } @ExtendWith(QuuxClassLevelCallbacks.class) static class ThirdLevelStaticHidingTestCase extends SecondLevelTestCase { @BeforeAll static void beforeAll1() { callSequence.add("beforeAllMethod-1-hidden"); } @BeforeAll static void beforeAll2() { callSequence.add("beforeAllMethod-2-hidden"); } @BeforeAll static void beforeAll3() { callSequence.add("beforeAllMethod-3"); } @AfterAll static void afterAll1() { callSequence.add("afterAllMethod-1-hidden"); } @AfterAll static void afterAll2() { callSequence.add("afterAllMethod-2-hidden"); } @AfterAll static void afterAll3() { callSequence.add("afterAllMethod-3"); } @Test @Override void test() { callSequence.add("test-3"); } } @ExtendWith(FooClassLevelCallbacks.class) static class ExceptionInBeforeAllMethodTestCase { @BeforeAll static void beforeAll() { callSequence.add("beforeAllMethod"); throw new EnigmaException("@BeforeAll"); } @Test void test() { callSequence.add("test"); } @AfterAll static void afterAll() { callSequence.add("afterAllMethod"); } } @ExtendWith({ FooClassLevelCallbacks.class, ExceptionThrowingBeforeAllCallback.class }) static class ExceptionInBeforeAllCallbackTestCase { @BeforeAll static void beforeAll() { callSequence.add("beforeAllMethod"); } @Test void test() { callSequence.add("test"); } @AfterAll static void afterAll() { callSequence.add("afterAllMethod"); } } // ------------------------------------------------------------------------- static class FooClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback { @Override public void beforeAll(ExtensionContext context) { callSequence.add("fooBeforeAllCallback"); } @Override public void afterAll(ExtensionContext context) { callSequence.add("fooAfterAllCallback"); actualExceptionInAfterAllCallback = context.getExecutionException(); } } static class BarClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback { @Override public void beforeAll(ExtensionContext context) { callSequence.add("barBeforeAllCallback"); } @Override public void afterAll(ExtensionContext context) { callSequence.add("barAfterAllCallback"); } } static class BazClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback { @Override public void beforeAll(ExtensionContext context) { callSequence.add("bazBeforeAllCallback"); } @Override public void afterAll(ExtensionContext context) { callSequence.add("bazAfterAllCallback"); } } static class QuuxClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback { @Override public void beforeAll(ExtensionContext context) { callSequence.add("quuxBeforeAllCallback"); } @Override public void afterAll(ExtensionContext context) { callSequence.add("quuxAfterAllCallback"); } } static class ExceptionThrowingBeforeAllCallback implements BeforeAllCallback { @Override public void beforeAll(ExtensionContext context) { callSequence.add("exceptionThrowingBeforeAllCallback"); throw new EnigmaException("BeforeAllCallback"); } } } BeforeAndAfterEachTests.java000066400000000000000000000351101455764576500360540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.testkit.engine.Events; /** * Integration tests that verify support for {@link BeforeEach}, {@link AfterEach}, * {@link BeforeEachCallback}, and {@link AfterEachCallback} in the {@link JupiterTestEngine}. * * @since 5.0 * @see BeforeAndAfterTestExecutionCallbackTests */ class BeforeAndAfterEachTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); private static final List beforeEachMethodCallSequence = new ArrayList<>(); private static Optional actualExceptionInAfterEachCallback; @BeforeEach void resetCallSequence() { callSequence.clear(); beforeEachMethodCallSequence.clear(); actualExceptionInAfterEachCallback = null; } @Test void beforeEachAndAfterEachCallbacks() { Events testEvents = executeTestsForClass(OuterTestCase.class).testEvents(); assertEquals(2, testEvents.started().count(), "# tests started"); assertEquals(2, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(0, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( // OuterTestCase "fooBeforeEachCallback", "barBeforeEachCallback", "beforeEachMethod", "testOuter", "afterEachMethod", "barAfterEachCallback", "fooAfterEachCallback", // InnerTestCase "fooBeforeEachCallback", "barBeforeEachCallback", "fizzBeforeEachCallback", "beforeEachMethod", "beforeEachInnerMethod", "testInner", "afterEachInnerMethod", "afterEachMethod", "fizzAfterEachCallback", "barAfterEachCallback", "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeEachAndAfterEachCallbacksDeclaredOnSuperclassAndSubclass() { Events testEvents = executeTestsForClass(ChildTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(1, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(0, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeEachCallback", "barBeforeEachCallback", "testChild", "barAfterEachCallback", "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeEachAndAfterEachCallbacksDeclaredOnInterfaceAndClass() { Events testEvents = executeTestsForClass(TestInterfaceTestCase.class).testEvents(); assertEquals(2, testEvents.started().count(), "# tests started"); assertEquals(2, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(0, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( // Test Interface "fooBeforeEachCallback", "barBeforeEachCallback", "defaultTestMethod", "barAfterEachCallback", "fooAfterEachCallback", // Test Class "fooBeforeEachCallback", "barBeforeEachCallback", "localTestMethod", "barAfterEachCallback", "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeEachCallbackThrowsAnException() { Events testEvents = executeTestsForClass(ExceptionInBeforeEachCallbackTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(0, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(1, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeEachCallback", "exceptionThrowingBeforeEachCallback", // throws an exception. // barBeforeEachCallback should not get invoked. // beforeEachMethod should not get invoked. // test should not get invoked. // afterEachMethod should not get invoked. "barAfterEachCallback", "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on assertThat(actualExceptionInAfterEachCallback).containsInstanceOf(EnigmaException.class); } @Test void afterEachCallbackThrowsAnException() { Events testEvents = executeTestsForClass(ExceptionInAfterEachCallbackTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(0, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(1, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeEachCallback", "barBeforeEachCallback", "beforeEachMethod", "test", "afterEachMethod", "barAfterEachCallback", "exceptionThrowingAfterEachCallback", // throws an exception. "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on assertThat(actualExceptionInAfterEachCallback).containsInstanceOf(EnigmaException.class); } @Test void beforeEachMethodThrowsAnException() { Events testEvents = executeTestsForClass(ExceptionInBeforeEachMethodTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(0, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(1, testEvents.failed().count(), "# tests failed"); // Since the JVM does not guarantee the order in which methods are // returned via reflection (and since JUnit Jupiter does not yet // support ordering of @BeforeEach methods), we have to figure out // which @BeforeEach method got executed first in order to determine // the expected call sequence. // @formatter:off List list1 = asList( "fooBeforeEachCallback", "beforeEachMethod1", // throws an exception. // "beforeEachMethod2" should not get invoked // test should not get invoked. "afterEachMethod", "fooAfterEachCallback" ); List list2 = asList( "fooBeforeEachCallback", "beforeEachMethod2", "beforeEachMethod1", // throws an exception. // test should not get invoked. "afterEachMethod", "fooAfterEachCallback" ); // @formatter:on List expected = beforeEachMethodCallSequence.get(0).equals("beforeEachMethod1") ? list1 : list2; assertEquals(expected, callSequence, "wrong call sequence"); assertThat(actualExceptionInAfterEachCallback).containsInstanceOf(EnigmaException.class); } @Test void afterEachMethodThrowsAnException() { Events testEvents = executeTestsForClass(ExceptionInAfterEachMethodTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(0, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(1, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeEachCallback", "beforeEachMethod", "test", "afterEachMethod", // throws an exception. "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on assertThat(actualExceptionInAfterEachCallback).containsInstanceOf(EnigmaException.class); } @Test void testMethodThrowsAnException() { Events testEvents = executeTestsForClass(ExceptionInTestMethodTestCase.class).testEvents(); assertEquals(1, testEvents.started().count(), "# tests started"); assertEquals(0, testEvents.succeeded().count(), "# tests succeeded"); assertEquals(0, testEvents.skipped().count(), "# tests skipped"); assertEquals(0, testEvents.aborted().count(), "# tests aborted"); assertEquals(1, testEvents.failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeEachCallback", "beforeEachMethod", "test", // throws an exception. "afterEachMethod", "fooAfterEachCallback" ), callSequence, "wrong call sequence"); // @formatter:on assertThat(actualExceptionInAfterEachCallback).containsInstanceOf(EnigmaException.class); } // ------------------------------------------------------------------------- @ExtendWith(FooMethodLevelCallbacks.class) static class ParentTestCase { } @ExtendWith(BarMethodLevelCallbacks.class) static class ChildTestCase extends ParentTestCase { @Test void test() { callSequence.add("testChild"); } } @ExtendWith(FooMethodLevelCallbacks.class) private interface TestInterface { @Test default void defaultTest() { callSequence.add("defaultTestMethod"); } } @ExtendWith(BarMethodLevelCallbacks.class) static class TestInterfaceTestCase implements TestInterface { @Test void localTest() { callSequence.add("localTestMethod"); } } @ExtendWith({ FooMethodLevelCallbacks.class, BarMethodLevelCallbacks.class }) static class OuterTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void testOuter() { callSequence.add("testOuter"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } @Nested @ExtendWith(FizzMethodLevelCallbacks.class) class InnerTestCase { @BeforeEach void beforeEachInnerMethod() { callSequence.add("beforeEachInnerMethod"); } @Test void testInner() { callSequence.add("testInner"); } @AfterEach void afterEachInnerMethod() { callSequence.add("afterEachInnerMethod"); } } } @ExtendWith({ FooMethodLevelCallbacks.class, ExceptionThrowingBeforeEachCallback.class, BarMethodLevelCallbacks.class }) static class ExceptionInBeforeEachCallbackTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith({ FooMethodLevelCallbacks.class, ExceptionThrowingAfterEachCallback.class, BarMethodLevelCallbacks.class }) static class ExceptionInAfterEachCallbackTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith(FooMethodLevelCallbacks.class) static class ExceptionInBeforeEachMethodTestCase { @BeforeEach void beforeEach1() { beforeEachMethodCallSequence.add("beforeEachMethod1"); callSequence.add("beforeEachMethod1"); throw new EnigmaException("@BeforeEach"); } @BeforeEach void beforeEach2() { beforeEachMethodCallSequence.add("beforeEachMethod2"); callSequence.add("beforeEachMethod2"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith(FooMethodLevelCallbacks.class) static class ExceptionInAfterEachMethodTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); throw new EnigmaException("@AfterEach"); } } @ExtendWith(FooMethodLevelCallbacks.class) static class ExceptionInTestMethodTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); throw new EnigmaException("@Test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } // ------------------------------------------------------------------------- static class FooMethodLevelCallbacks implements BeforeEachCallback, AfterEachCallback { @Override public void beforeEach(ExtensionContext context) { callSequence.add("fooBeforeEachCallback"); } @Override public void afterEach(ExtensionContext context) { callSequence.add("fooAfterEachCallback"); actualExceptionInAfterEachCallback = context.getExecutionException(); } } static class BarMethodLevelCallbacks implements BeforeEachCallback, AfterEachCallback { @Override public void beforeEach(ExtensionContext context) { callSequence.add("barBeforeEachCallback"); } @Override public void afterEach(ExtensionContext context) { callSequence.add("barAfterEachCallback"); } } static class FizzMethodLevelCallbacks implements BeforeEachCallback, AfterEachCallback { @Override public void beforeEach(ExtensionContext context) { callSequence.add("fizzBeforeEachCallback"); } @Override public void afterEach(ExtensionContext context) { callSequence.add("fizzAfterEachCallback"); } } static class ExceptionThrowingBeforeEachCallback implements BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { callSequence.add("exceptionThrowingBeforeEachCallback"); throw new EnigmaException("BeforeEachCallback"); } } static class ExceptionThrowingAfterEachCallback implements AfterEachCallback { @Override public void afterEach(ExtensionContext context) { callSequence.add("exceptionThrowingAfterEachCallback"); throw new EnigmaException("AfterEachCallback"); } } } BeforeAndAfterTestExecutionCallbackTests.java000066400000000000000000000350401455764576500414360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for {@link BeforeTestExecutionCallback}, * {@link AfterTestExecutionCallback}, {@link BeforeEach}, and {@link AfterEach} * in the {@link JupiterTestEngine}. * * @since 5.0 * @see BeforeAndAfterEachTests */ class BeforeAndAfterTestExecutionCallbackTests extends AbstractJupiterTestEngineTests { private static List callSequence = new ArrayList<>(); private static Optional actualExceptionInAfterTestExecution; @BeforeEach void resetCallSequence() { callSequence.clear(); actualExceptionInAfterTestExecution = null; } @Test void beforeAndAfterTestExecutionCallbacks() { EngineExecutionResults executionResults = executeTestsForClass(OuterTestCase.class); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( // OuterTestCase "beforeEachMethodOuter", "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "testOuter", "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback", "afterEachMethodOuter", // InnerTestCase "beforeEachMethodOuter", "beforeEachMethodInner", "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "fizzBeforeTestExecutionCallback", "testInner", "fizzAfterTestExecutionCallback", "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback", "afterEachMethodInner", "afterEachMethodOuter" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeAndAfterTestExecutionCallbacksDeclaredOnSuperclassAndSubclass() { EngineExecutionResults executionResults = executeTestsForClass(ChildTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "testChild", "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeAndAfterTestExecutionCallbacksDeclaredOnInterfaceAndClass() { EngineExecutionResults executionResults = executeTestsForClass(TestInterfaceTestCase.class); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( // Test Interface "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "defaultTestMethod", "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback", // Test Class "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "localTestMethod", "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback" ), callSequence, "wrong call sequence"); // @formatter:on } @Test void beforeEachMethodThrowsAnException() { EngineExecutionResults executionResults = executeTestsForClass(ExceptionInBeforeEachMethodTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "beforeEachMethod", // throws an exception. // fooBeforeTestExecutionCallback should not get invoked. // test should not get invoked. // fooAfterTestExecutionCallback should not get invoked. "afterEachMethod" ), callSequence, "wrong call sequence"); // @formatter:on assertNull(actualExceptionInAfterTestExecution, "test exception (fooAfterTestExecutionCallback should not have been called)"); } @Test void beforeTestExecutionCallbackThrowsAnException() { EngineExecutionResults executionResults = executeTestsForClass( ExceptionInBeforeTestExecutionCallbackTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "beforeEachMethod", "fooBeforeTestExecutionCallback", "exceptionThrowingBeforeTestExecutionCallback", // throws an exception. // barBeforeTestExecutionCallback should not get invoked. // test() should not get invoked. "barAfterTestExecutionCallback", "fooAfterTestExecutionCallback", "afterEachMethod" ), callSequence, "wrong call sequence"); // @formatter:on assertNotNull(actualExceptionInAfterTestExecution, "test exception"); assertTrue(actualExceptionInAfterTestExecution.isPresent(), "test exception should be present"); assertEquals(EnigmaException.class, actualExceptionInAfterTestExecution.get().getClass()); } @Test void afterTestExecutionCallbackThrowsAnException() { EngineExecutionResults executionResults = executeTestsForClass( ExceptionInAfterTestExecutionCallbackTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "beforeEachMethod", "fooBeforeTestExecutionCallback", "barBeforeTestExecutionCallback", "test", "barAfterTestExecutionCallback", "exceptionThrowingAfterTestExecutionCallback", // throws an exception. "fooAfterTestExecutionCallback", "afterEachMethod" ), callSequence, "wrong call sequence"); // @formatter:on assertNotNull(actualExceptionInAfterTestExecution, "test exception"); assertTrue(actualExceptionInAfterTestExecution.isPresent(), "test exception should be present"); assertEquals(EnigmaException.class, actualExceptionInAfterTestExecution.get().getClass()); } @Test void testMethodThrowsAnException() { EngineExecutionResults executionResults = executeTestsForClass(ExceptionInTestMethodTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off assertEquals(asList( "beforeEachMethod", "fooBeforeTestExecutionCallback", "test", // throws an exception. "fooAfterTestExecutionCallback", "afterEachMethod" ), callSequence, "wrong call sequence"); // @formatter:on assertNotNull(actualExceptionInAfterTestExecution, "test exception"); assertTrue(actualExceptionInAfterTestExecution.isPresent(), "test exception should be present"); assertEquals(EnigmaException.class, actualExceptionInAfterTestExecution.get().getClass()); } // ------------------------------------------------------------------------- @ExtendWith(FooTestExecutionCallbacks.class) static class ParentTestCase { } @ExtendWith(BarTestExecutionCallbacks.class) static class ChildTestCase extends ParentTestCase { @Test void test() { callSequence.add("testChild"); } } @ExtendWith(FooTestExecutionCallbacks.class) private interface TestInterface { @Test default void defaultTest() { callSequence.add("defaultTestMethod"); } } @ExtendWith(BarTestExecutionCallbacks.class) static class TestInterfaceTestCase implements TestInterface { @Test void localTest() { callSequence.add("localTestMethod"); } } @ExtendWith({ FooTestExecutionCallbacks.class, BarTestExecutionCallbacks.class }) static class OuterTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethodOuter"); } @Test void testOuter() { callSequence.add("testOuter"); } @AfterEach void afterEach() { callSequence.add("afterEachMethodOuter"); } @Nested @ExtendWith(FizzTestExecutionCallbacks.class) class InnerTestCase { @BeforeEach void beforeInnerMethod() { callSequence.add("beforeEachMethodInner"); } @Test void testInner() { callSequence.add("testInner"); } @AfterEach void afterInnerMethod() { callSequence.add("afterEachMethodInner"); } } } @ExtendWith({ FooTestExecutionCallbacks.class, ExceptionThrowingBeforeTestExecutionCallback.class, BarTestExecutionCallbacks.class }) static class ExceptionInBeforeTestExecutionCallbackTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith({ FooTestExecutionCallbacks.class, ExceptionThrowingAfterTestExecutionCallback.class, BarTestExecutionCallbacks.class }) static class ExceptionInAfterTestExecutionCallbackTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith(FooTestExecutionCallbacks.class) static class ExceptionInBeforeEachMethodTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); throw new EnigmaException("@BeforeEach"); } @Test void test() { callSequence.add("test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } @ExtendWith(FooTestExecutionCallbacks.class) static class ExceptionInTestMethodTestCase { @BeforeEach void beforeEach() { callSequence.add("beforeEachMethod"); } @Test void test() { callSequence.add("test"); throw new EnigmaException("@Test"); } @AfterEach void afterEach() { callSequence.add("afterEachMethod"); } } // ------------------------------------------------------------------------- static class FooTestExecutionCallbacks implements BeforeTestExecutionCallback, AfterTestExecutionCallback { @Override public void beforeTestExecution(ExtensionContext context) { callSequence.add("fooBeforeTestExecutionCallback"); } @Override public void afterTestExecution(ExtensionContext context) { callSequence.add("fooAfterTestExecutionCallback"); actualExceptionInAfterTestExecution = context.getExecutionException(); } } static class BarTestExecutionCallbacks implements BeforeTestExecutionCallback, AfterTestExecutionCallback { @Override public void beforeTestExecution(ExtensionContext context) { callSequence.add("barBeforeTestExecutionCallback"); } @Override public void afterTestExecution(ExtensionContext context) { callSequence.add("barAfterTestExecutionCallback"); } } static class FizzTestExecutionCallbacks implements BeforeTestExecutionCallback, AfterTestExecutionCallback { @Override public void beforeTestExecution(ExtensionContext context) { callSequence.add("fizzBeforeTestExecutionCallback"); } @Override public void afterTestExecution(ExtensionContext context) { callSequence.add("fizzAfterTestExecutionCallback"); } } static class ExceptionThrowingBeforeTestExecutionCallback implements BeforeTestExecutionCallback { @Override public void beforeTestExecution(ExtensionContext context) { callSequence.add("exceptionThrowingBeforeTestExecutionCallback"); throw new EnigmaException("BeforeTestExecutionCallback"); } } static class ExceptionThrowingAfterTestExecutionCallback implements AfterTestExecutionCallback { @Override public void afterTestExecution(ExtensionContext context) { callSequence.add("exceptionThrowingAfterTestExecutionCallback"); throw new EnigmaException("AfterTestExecutionCallback"); } } } CloseablePathCleanupTests.java000066400000000000000000000101171455764576500365020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.nio.file.Files.deleteIfExists; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.api.io.CleanupMode.NEVER; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; import java.util.Optional; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.execution.NamespaceAwareStore; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; /** * Integration tests for cleanup of the {@link TempDirectory} when the {@link CleanupMode} is * set to {@link CleanupMode#ALWAYS}, {@link CleanupMode#NEVER}, or {@link CleanupMode#ON_SUCCESS}. * * @since 5.9 * * @see TempDir * @see CleanupMode */ class CloseablePathCleanupTests extends AbstractJupiterTestEngineTests { private final AnnotatedElementContext elementContext = mock(); private final ExtensionContext extensionContext = mock(); private final TempDirFactory factory = spy(TempDirFactory.Standard.INSTANCE); private TempDirectory.CloseablePath closeablePath; @BeforeEach void setUpExtensionContext() { var store = new NamespaceAwareStore(new NamespacedHierarchicalStore<>(null), Namespace.GLOBAL); when(extensionContext.getStore(any())).thenReturn(store); } @AfterEach void cleanupTempDirectory() throws IOException { deleteIfExists(closeablePath.get()); } @Test @DisplayName("is cleaned up for a cleanup mode of ALWAYS") void always() throws IOException { closeablePath = TempDirectory.createTempDir(factory, ALWAYS, elementContext, extensionContext); assertThat(closeablePath.get()).exists(); closeablePath.close(); assertThat(closeablePath.get()).doesNotExist(); verify(factory).close(); } @Test @DisplayName("is not cleaned up for a cleanup mode of NEVER") void never() throws IOException { closeablePath = TempDirectory.createTempDir(factory, NEVER, elementContext, extensionContext); assertThat(closeablePath.get()).exists(); closeablePath.close(); assertThat(closeablePath.get()).exists(); verify(factory).close(); } @Test @DisplayName("is not cleaned up for a cleanup mode of ON_SUCCESS, if there is an exception") void onSuccessWithException() throws IOException { when(extensionContext.getExecutionException()).thenReturn(Optional.of(new Exception())); closeablePath = TempDirectory.createTempDir(factory, ON_SUCCESS, elementContext, extensionContext); assertThat(closeablePath.get()).exists(); closeablePath.close(); assertThat(closeablePath.get()).exists(); verify(factory).close(); } @Test @DisplayName("is cleaned up for a cleanup mode of ON_SUCCESS, if there is no exception") void onSuccessWithNoException() throws IOException { when(extensionContext.getExecutionException()).thenReturn(Optional.empty()); closeablePath = TempDirectory.createTempDir(factory, ON_SUCCESS, elementContext, extensionContext); assertThat(closeablePath.get()).exists(); closeablePath.close(); assertThat(closeablePath.get()).doesNotExist(); verify(factory).close(); } } EnigmaException.java000066400000000000000000000007611455764576500345240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; @SuppressWarnings("serial") class EnigmaException extends RuntimeException { EnigmaException(String message) { super(message); } } EventuallyInterruptibleInvocation.java000066400000000000000000000014441455764576500403770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import java.util.stream.IntStream; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; /** * @since 5.5 */ class EventuallyInterruptibleInvocation implements Invocation { @Override public Void proceed() { while (!Thread.currentThread().isInterrupted()) { assertThat(IntStream.range(1, 1_000_000).sum()).isGreaterThan(0); } return null; } } ExecutionConditionTests.java000066400000000000000000000161021455764576500362760ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.engine.Constants.DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.engine.extension.sub.AlwaysDisabledCondition; import org.junit.jupiter.engine.extension.sub.AnotherAlwaysDisabledCondition; import org.junit.jupiter.engine.extension.sub.SystemPropertyCondition; import org.junit.jupiter.engine.extension.sub.SystemPropertyCondition.SystemProperty; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests that verify support for the {@link ExecutionCondition} * extension point in the {@link JupiterTestEngine}. * * @since 5.0 */ class ExecutionConditionTests extends AbstractJupiterTestEngineTests { private static final String FOO = "DisabledTests.foo"; private static final String BAR = "DisabledTests.bar"; private static final String BOGUS = "DisabledTests.bogus"; private static final String DEACTIVATE = "*AnotherAlwaysDisable*, org.junit.jupiter.engine.extension.sub.AlwaysDisable*"; @BeforeEach public void setUp() { System.setProperty(FOO, BAR); } @AfterEach public void tearDown() { System.clearProperty(FOO); } @Test void conditionWorksOnContainer() { EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithExecutionConditionOnClass.class); executionResults.containerEvents().assertStatistics(stats -> stats.skipped(1)); executionResults.testEvents().assertStatistics(stats -> stats.started(0)); } @Test void conditionWorksOnTest() { Events tests = executeTestsForClass(TestCaseWithExecutionConditionOnMethods.class).testEvents(); tests.assertStatistics(stats -> stats.started(2).succeeded(2).skipped(3)); } @Test void overrideConditionsUsingFullyQualifiedClassName() { String deactivatePattern = SystemPropertyCondition.class.getName() + "," + DEACTIVATE; assertExecutionConditionOverride(deactivatePattern, 1, 1); assertExecutionConditionOverride(deactivatePattern, 4, 2, 2); } @Test void overrideConditionsUsingStar() { // "*" should deactivate DisabledCondition and SystemPropertyCondition String deactivatePattern = "*"; assertExecutionConditionOverride(deactivatePattern, 2, 2); assertExecutionConditionOverride(deactivatePattern, 5, 2, 3); } @Test void overrideConditionsUsingStarPlusSimpleClassName() { // DisabledCondition should remain activated String deactivatePattern = "*" + SystemPropertyCondition.class.getSimpleName() + ", " + DEACTIVATE; assertExecutionConditionOverride(deactivatePattern, 1, 1); assertExecutionConditionOverride(deactivatePattern, 4, 2, 2); } @Test void overrideConditionsUsingPackageNamePlusDotStar() { // DisabledCondition should remain activated String deactivatePattern = DEACTIVATE + ", " + SystemPropertyCondition.class.getPackage().getName() + ".*"; assertExecutionConditionOverride(deactivatePattern, 1, 1); assertExecutionConditionOverride(deactivatePattern, 4, 2, 2); } @Test void overrideConditionsUsingMultipleWildcards() { // DisabledCondition should remain activated String deactivatePattern = "org.junit.jupiter.*.System*Condition" + "," + DEACTIVATE; assertExecutionConditionOverride(deactivatePattern, 1, 1); assertExecutionConditionOverride(deactivatePattern, 4, 2, 2); } @Test void deactivateAllConditions() { // DisabledCondition should remain activated String deactivatePattern = "org.junit.jupiter.*.System*Condition" + ", " + DEACTIVATE; assertExecutionConditionOverride(deactivatePattern, 1, 1); assertExecutionConditionOverride(deactivatePattern, 4, 2, 2); } private void assertExecutionConditionOverride(String deactivatePattern, int testStartedCount, int testFailedCount) { // @formatter:off LauncherDiscoveryRequest request = request() .selectors(selectClass(TestCaseWithExecutionConditionOnClass.class)) .configurationParameter(DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME, deactivatePattern) .build(); // @formatter:on EngineExecutionResults executionResults = executeTests(request); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); containers.assertStatistics(stats -> stats.skipped(0).started(2)); tests.assertStatistics(stats -> stats.started(testStartedCount).failed(testFailedCount)); } private void assertExecutionConditionOverride(String deactivatePattern, int started, int succeeded, int failed) { // @formatter:off LauncherDiscoveryRequest request = request() .selectors(selectClass(TestCaseWithExecutionConditionOnMethods.class)) .configurationParameter(DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME, deactivatePattern) .build(); // @formatter:on executeTests(request).testEvents().assertStatistics( stats -> stats.started(started).succeeded(succeeded).failed(failed)); } // ------------------------------------------------------------------- @SystemProperty(key = FOO, value = BOGUS) @DeactivatedConditions static class TestCaseWithExecutionConditionOnClass { @Test void disabledTest() { fail("this should be disabled"); } @Test @Disabled void atDisabledTest() { fail("this should be @Disabled"); } } static class TestCaseWithExecutionConditionOnMethods { @Test void enabledTest() { } @Test @Disabled @DeactivatedConditions void atDisabledTest() { fail("this should be @Disabled"); } @Test @SystemProperty(key = FOO, value = BAR) void systemPropertyEnabledTest() { } @Test @DeactivatedConditions @SystemProperty(key = FOO, value = BOGUS) void systemPropertyWithIncorrectValueTest() { fail("this should be disabled"); } @Test @DeactivatedConditions @SystemProperty(key = BOGUS, value = "doesn't matter") void systemPropertyNotSetTest() { fail("this should be disabled"); } } @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @ExtendWith({ AlwaysDisabledCondition.class, AnotherAlwaysDisabledCondition.class }) @interface DeactivatedConditions { } } ExtensionContextExecutionTests.java000066400000000000000000000054011455764576500376710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.lang.reflect.Method; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContextParameterResolver; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; class ExtensionContextExecutionTests extends AbstractJupiterTestEngineTests { @Test @ExtendWith(ExtensionContextParameterResolver.class) void extensionContextHierarchy(ExtensionContext methodExtensionContext) { assertThat(methodExtensionContext).isNotNull(); assertThat(methodExtensionContext.getElement()).containsInstanceOf(Method.class); Optional classExtensionContext = methodExtensionContext.getParent(); assertThat(classExtensionContext).isNotEmpty(); assertThat(classExtensionContext.orElse(null).getElement()).contains(ExtensionContextExecutionTests.class); Optional engineExtensionContext = classExtensionContext.orElse(null).getParent(); assertThat(engineExtensionContext).isNotEmpty(); assertThat(engineExtensionContext.orElse(null).getElement()).isEmpty(); assertThat(engineExtensionContext.orElse(null).getParent()).isEmpty(); } @Test void twoTestClassesCanShareStateViaEngineExtensionContext() { Parent.counter.set(0); executeTests(selectClass(A.class), selectClass(B.class)).testEvents()// .assertStatistics(stats -> stats.started(2)); assertThat(Parent.counter).hasValue(1); } @ExtendWith(OnlyIncrementCounterOnce.class) static class Parent { static final AtomicInteger counter = new AtomicInteger(0); @Test void test() { } } static class A extends Parent { } static class B extends Parent { } static class OnlyIncrementCounterOnce implements BeforeAllCallback { @Override public void beforeAll(ExtensionContext context) { ExtensionContext.Store store = getRoot(context).getStore(ExtensionContext.Namespace.GLOBAL); store.getOrComputeIfAbsent("counter", key -> Parent.counter.incrementAndGet()); } private ExtensionContext getRoot(ExtensionContext context) { return context.getParent().map(this::getRoot).orElse(context); } } } ExtensionRegistrationViaParametersAndFieldsTests.java000066400000000000000000000721261455764576500433010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields; import static org.junit.platform.commons.util.ReflectionUtils.makeAccessible; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.execution.injection.sample.LongParameterResolver; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; /** * Integration tests that verify support for extension registration via * {@link ExtendWith @ExtendWith} on parameters and fields. * * @since 5.8 */ class ExtensionRegistrationViaParametersAndFieldsTests extends AbstractJupiterTestEngineTests { @Test void constructorParameter() { assertOneTestSucceeded(ConstructorParameterTestCase.class); } @Test void constructorParameterForNestedTestClass() { assertTestsSucceeded(NestedConstructorParameterTestCase.class, 2); } @Test void beforeAllMethodParameter() { assertOneTestSucceeded(BeforeAllParameterTestCase.class); } @Test void afterAllMethodParameter() { assertOneTestSucceeded(AfterAllParameterTestCase.class); } @Test void beforeEachMethodParameter() { assertOneTestSucceeded(BeforeEachParameterTestCase.class); } @Test void afterEachMethodParameter() { assertOneTestSucceeded(AfterEachParameterTestCase.class); } @Test void testMethodParameter() { assertOneTestSucceeded(TestMethodParameterTestCase.class); } @Test void testFactoryMethodParameter() { assertTestsSucceeded(TestFactoryMethodParameterTestCase.class, 2); } @Test void testTemplateMethodParameter() { assertTestsSucceeded(TestTemplateMethodParameterTestCase.class, 2); } @Test void staticField() { assertOneTestSucceeded(StaticFieldTestCase.class); } @Test void instanceField() { assertOneTestSucceeded(InstanceFieldTestCase.class); } @Test void fieldsWithTestInstancePerClass() { assertOneTestSucceeded(TestInstancePerClassFieldTestCase.class); } @Test @TrackLogRecords void multipleRegistrationsViaField(LogRecordListener listener) { assertOneTestSucceeded(MultipleRegistrationsViaFieldTestCase.class); assertThat(getRegisteredLocalExtensions(listener)).containsExactly("LongParameterResolver", "DummyExtension"); } @Test void duplicateRegistrationViaField() { Class testClass = DuplicateRegistrationViaFieldTestCase.class; String expectedMessage = "Failed to register extension via field " + "[org.junit.jupiter.api.extension.Extension " + "org.junit.jupiter.engine.extension.ExtensionRegistrationViaParametersAndFieldsTests$DuplicateRegistrationViaFieldTestCase.dummy]. " + "The field registers an extension of type [org.junit.jupiter.engine.extension.DummyExtension] " + "via @RegisterExtension and @ExtendWith, but only one registration of a given extension type is permitted."; executeTestsForClass(testClass).testEvents().assertThatEvents().haveExactly(1, finishedWithFailure(instanceOf(PreconditionViolationException.class), message(expectedMessage))); } @Test @TrackLogRecords void registrationOrder(LogRecordListener listener) { assertOneTestSucceeded(AllInOneWithTestInstancePerMethodTestCase.class); assertThat(getRegisteredLocalExtensions(listener))// .containsExactly(// "ClassLevelExtension2", // @RegisterExtension on static field "StaticField2", // @ExtendWith on static field "ClassLevelExtension1", // @RegisterExtension on static field "StaticField1", // @ExtendWith on static field "ConstructorParameter", // @ExtendWith on parameter in constructor "BeforeAllParameter", // @ExtendWith on parameter in static @BeforeAll method "BeforeEachParameter", // @ExtendWith on parameter in @BeforeEach method "AfterEachParameter", // @ExtendWith on parameter in @AfterEach method "AfterAllParameter", // @ExtendWith on parameter in static @AfterAll method "TestParameter", // @ExtendWith on parameter in @Test method "InstanceLevelExtension1", // @RegisterExtension on instance field "InstanceField1", // @ExtendWith on instance field "InstanceLevelExtension2", // @RegisterExtension on instance field "InstanceField2" // @ExtendWith on instance field ); listener.clear(); assertOneTestSucceeded(AllInOneWithTestInstancePerClassTestCase.class); assertThat(getRegisteredLocalExtensions(listener))// .containsExactly(// "ClassLevelExtension2", // @RegisterExtension on static field "StaticField2", // @ExtendWith on static field "ClassLevelExtension1", // @RegisterExtension on static field "StaticField1", // @ExtendWith on static field "ConstructorParameter", // @ExtendWith on parameter in constructor "BeforeAllParameter", // @ExtendWith on parameter in static @BeforeAll method "BeforeEachParameter", // @ExtendWith on parameter in @BeforeEach method "AfterEachParameter", // @ExtendWith on parameter in @AfterEach method "AfterAllParameter", // @ExtendWith on parameter in static @AfterAll method "InstanceLevelExtension1", // @RegisterExtension on instance field "InstanceField1", // @ExtendWith on instance field "InstanceLevelExtension2", // @RegisterExtension on instance field "InstanceField2", // @ExtendWith on instance field "TestParameter" // @ExtendWith on parameter in @Test method ); } private List getRegisteredLocalExtensions(LogRecordListener listener) { // @formatter:off return listener.stream(MutableExtensionRegistry.class, Level.FINER) .map(LogRecord::getMessage) .filter(message -> message.contains("local extension")) .map(message -> { message = message.replaceAll("from source .+", ""); int indexOfDollarSign = message.indexOf("$"); int indexOfAtSign = message.indexOf("@"); int endIndex = (indexOfDollarSign > 1 ? indexOfDollarSign : indexOfAtSign); return message.substring(message.lastIndexOf('.') + 1, endIndex); }) .collect(toList()); // @formatter:on } private void assertOneTestSucceeded(Class testClass) { assertTestsSucceeded(testClass, 1); } private void assertTestsSucceeded(Class testClass, int expected) { executeTestsForClass(testClass).testEvents().assertStatistics( stats -> stats.started(expected).succeeded(expected).skipped(0).aborted(0).failed(0)); } // ------------------------------------------------------------------- /** * The {@link MagicParameter.Extension} is first registered for the constructor * and then used for lifecycle and test methods. */ @ExtendWith(LongParameterResolver.class) static class ConstructorParameterTestCase { ConstructorParameterTestCase(@MagicParameter("constructor") String text) { assertThat(text).isEqualTo("ConstructorParameterTestCase-0-constructor"); } @BeforeEach void beforeEach(String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeEach-0-enigma"); assertThat(testInfo).isNotNull(); } @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } /** * Redeclaring {@code @MagicParameter} should not result in a * {@link ParameterResolutionException}. */ @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } } /** * The {@link MagicParameter.Extension} is first registered for the constructor * and then used for lifecycle and test methods. */ @Nested @ExtendWith(LongParameterResolver.class) class NestedConstructorParameterTestCase { NestedConstructorParameterTestCase(TestInfo testInfo, @MagicParameter("constructor") String text) { assertThat(testInfo).isNotNull(); // Index is 2 instead of 1, since constructors for non-static nested classes // receive a reference to the enclosing instance as the first argument: this$0 assertThat(text).isEqualTo("NestedConstructorParameterTestCase-2-constructor"); } @BeforeEach void beforeEach(String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeEach-0-enigma"); assertThat(testInfo).isNotNull(); } @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } /** * Redeclaring {@code @MagicParameter} should not result in a * {@link ParameterResolutionException}. */ @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } @Nested class DoublyNestedConstructorParameterTestCase { DoublyNestedConstructorParameterTestCase(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); // Index is 2 instead of 1, since constructors for non-static nested classes // receive a reference to the enclosing instance as the first argument: this$0 assertThat(text).isEqualTo("DoublyNestedConstructorParameterTestCase-2-enigma"); } @BeforeEach void beforeEach(String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeEach-0-enigma"); assertThat(testInfo).isNotNull(); } @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } /** * Redeclaring {@code @MagicParameter} should not result in a * {@link ParameterResolutionException}. */ @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @BeforeAll} * method and then used for other lifecycle methods and test methods. */ @ExtendWith(LongParameterResolver.class) static class BeforeAllParameterTestCase { @BeforeAll static void beforeAll(@MagicParameter("method") String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeAll-0-method"); assertThat(testInfo).isNotNull(); } @BeforeEach void beforeEach(String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeEach-0-enigma"); assertThat(testInfo).isNotNull(); } @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } /** * Redeclaring {@code @MagicParameter} should not result in a * {@link ParameterResolutionException}. */ @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } @AfterAll static void afterAll(String text, TestInfo testInfo) { assertThat(text).isEqualTo("afterAll-0-enigma"); assertThat(testInfo).isNotNull(); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @AfterAll} * method, but that registration occurs before the test method is invoked, which * allows the string parameters in the after-each and test methods to be resolved * by the {@link MagicParameter.Extension} as well. */ @ExtendWith(LongParameterResolver.class) static class AfterAllParameterTestCase { @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } @AfterEach void afterEach(Long number, TestInfo testInfo, String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-enigma"); } @AfterAll static void afterAll(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterAll-2-method"); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @BeforeEach} * method and then used for other lifecycle methods and test methods. */ @ExtendWith(LongParameterResolver.class) static class BeforeEachParameterTestCase { @BeforeEach void beforeEach(@MagicParameter("method") String text, TestInfo testInfo) { assertThat(text).isEqualTo("beforeEach-0-method"); assertThat(testInfo).isNotNull(); } @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } /** * Redeclaring {@code @MagicParameter} should not result in a * {@link ParameterResolutionException}. */ @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @AfterEach} * method, but that registration occurs before the test method is invoked, which * allows the test method's parameter to be resolved by the {@link MagicParameter.Extension} * as well. */ @ExtendWith(LongParameterResolver.class) static class AfterEachParameterTestCase { @Test void test(TestInfo testInfo, String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-enigma"); } @AfterEach void afterEach(Long number, TestInfo testInfo, @MagicParameter("method") String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-method"); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @Test} * method and then used for after-each lifecycle methods. */ @ExtendWith(LongParameterResolver.class) static class TestMethodParameterTestCase { @Test void test(TestInfo testInfo, @MagicParameter("method") String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("test-1-method"); } @AfterEach void afterEach(Long number, TestInfo testInfo, String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-enigma"); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @TestFactory} * method and then used for after-each lifecycle methods. */ @ExtendWith(LongParameterResolver.class) static class TestFactoryMethodParameterTestCase { @TestFactory Stream testFactory(TestInfo testInfo, @MagicParameter("method") String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("testFactory-1-method"); return IntStream.of(2, 4).mapToObj(num -> dynamicTest("" + num, () -> assertTrue(num % 2 == 0))); } @AfterEach void afterEach(Long number, TestInfo testInfo, String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-enigma"); } } /** * The {@link MagicParameter.Extension} is first registered for the {@code @TestTemplate} * method and then used for after-each lifecycle methods. */ @ExtendWith(LongParameterResolver.class) static class TestTemplateMethodParameterTestCase { @TestTemplate @ExtendWith(TwoInvocationsContextProvider.class) void testTemplate(TestInfo testInfo, @MagicParameter("method") String text) { assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("testTemplate-1-method"); } @AfterEach void afterEach(Long number, TestInfo testInfo, String text) { assertThat(number).isEqualTo(42L); assertThat(testInfo).isNotNull(); assertThat(text).isEqualTo("afterEach-2-enigma"); } } private static class TwoInvocationsContextProvider implements TestTemplateInvocationContextProvider { @Override public boolean supportsTestTemplate(ExtensionContext context) { return true; } @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { return Stream.of(emptyTestTemplateInvocationContext(), emptyTestTemplateInvocationContext()); } private static TestTemplateInvocationContext emptyTestTemplateInvocationContext() { return new TestTemplateInvocationContext() { }; } } static class MultipleRegistrationsViaFieldTestCase { @ExtendWith(LongParameterResolver.class) @RegisterExtension Extension dummy = new DummyExtension(); @Test void test() { } } static class DuplicateRegistrationViaFieldTestCase { @ExtendWith(DummyExtension.class) @RegisterExtension Extension dummy = new DummyExtension(); @Test void test() { } } /** * The {@link MagicField.Extension} is registered via a static field. */ static class StaticFieldTestCase { @MagicField private static String staticField1; @MagicField static String staticField2; @BeforeAll static void beforeAll() { assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); } @Test void test() { assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); } } /** * The {@link MagicField.Extension} is registered via an instance field. */ static class InstanceFieldTestCase { @MagicField String instanceField1; @MagicField private String instanceField2; @Test void test() { assertThat(instanceField1).isEqualTo("beforeEach - instanceField1"); assertThat(instanceField2).isEqualTo("beforeEach - instanceField2"); } } /** * The {@link MagicField.Extension} is registered via a static field and * an instance field. */ @TestInstance(Lifecycle.PER_CLASS) static class TestInstancePerClassFieldTestCase { @MagicField static String staticField; @MagicField String instanceField; @BeforeAll void beforeAll() { assertThat(staticField).isEqualTo("beforeAll - staticField"); assertThat(instanceField).isNull(); } @Test void test() { assertThat(staticField).isEqualTo("beforeAll - staticField"); assertThat(instanceField).isEqualTo("beforeEach - instanceField"); } } @TestInstance(Lifecycle.PER_METHOD) static class AllInOneWithTestInstancePerMethodTestCase { @StaticField1 @Order(Integer.MAX_VALUE) static String staticField1; @StaticField2 @ExtendWith(StaticField2.Extension.class) @Order(3) static String staticField2; @RegisterExtension private static Extension classLevelExtension1 = new ClassLevelExtension1(); @RegisterExtension @Order(1) static Extension classLevelExtension2 = new ClassLevelExtension2(); @InstanceField1 @Order(2) String instanceField1; @InstanceField2 @ExtendWith(InstanceField2.Extension.class) String instanceField2; @RegisterExtension @Order(1) private Extension instanceLevelExtension1 = new InstanceLevelExtension1(); @RegisterExtension @Order(3) Extension instanceLevelExtension2 = new InstanceLevelExtension2(); AllInOneWithTestInstancePerMethodTestCase(@ConstructorParameter String text) { assertThat(text).isEqualTo("enigma"); } @BeforeAll static void beforeAll(@ExtendWith(BeforeAllParameter.Extension.class) @BeforeAllParameter String text) { assertThat(text).isEqualTo("enigma"); assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); } @BeforeEach void beforeEach(@BeforeEachParameter String text) { assertThat(text).isEqualTo("enigma"); assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); assertThat(instanceField1).isEqualTo("beforeEach - instanceField1"); assertThat(instanceField2).isEqualTo("beforeEach - instanceField2"); } @Test void test(@TestParameter String text) { assertThat(text).isEqualTo("enigma"); assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); assertThat(instanceField1).isEqualTo("beforeEach - instanceField1"); assertThat(instanceField2).isEqualTo("beforeEach - instanceField2"); } @AfterEach void afterEach(@AfterEachParameter String text) { assertThat(text).isEqualTo("enigma"); assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); assertThat(instanceField1).isEqualTo("beforeEach - instanceField1"); assertThat(instanceField2).isEqualTo("beforeEach - instanceField2"); } @AfterAll static void afterAll(@AfterAllParameter String text) { assertThat(text).isEqualTo("enigma"); assertThat(staticField1).isEqualTo("beforeAll - staticField1"); assertThat(staticField2).isEqualTo("beforeAll - staticField2"); } } @TestInstance(Lifecycle.PER_CLASS) static class AllInOneWithTestInstancePerClassTestCase extends AllInOneWithTestInstancePerMethodTestCase { AllInOneWithTestInstancePerClassTestCase(@ConstructorParameter String text) { super(text); } } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(MagicParameter.Extension.class) @interface MagicParameter { String value(); class Extension implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == String.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { String text = parameterContext.findAnnotation(MagicParameter.class)// .map(MagicParameter::value)// .orElse("enigma"); Executable declaringExecutable = parameterContext.getDeclaringExecutable(); String name = declaringExecutable instanceof Constructor ? declaringExecutable.getDeclaringClass().getSimpleName() : declaringExecutable.getName(); return String.format("%s-%d-%s", name, parameterContext.getIndex(), text); } } } @SuppressWarnings("unused") class BaseParameterExtension implements ParameterResolver { private final Class annotationType; @SuppressWarnings("unchecked") BaseParameterExtension() { Type genericSuperclass = getClass().getGenericSuperclass(); this.annotationType = (Class) ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0]; } @Override public final boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.isAnnotated(this.annotationType) && parameterContext.getParameter().getType() == String.class; } @Override public final Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return "enigma"; } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(ConstructorParameter.Extension.class) @interface ConstructorParameter { class Extension extends BaseParameterExtension { } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) // Intentionally NOT annotated as follows // @ExtendWith(BeforeAllParameter.Extension.class) @interface BeforeAllParameter { class Extension extends BaseParameterExtension { } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(AfterAllParameter.Extension.class) @interface AfterAllParameter { class Extension extends BaseParameterExtension { } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(BeforeEachParameter.Extension.class) @interface BeforeEachParameter { class Extension extends BaseParameterExtension { } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(AfterEachParameter.Extension.class) @interface AfterEachParameter { class Extension extends BaseParameterExtension { } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(TestParameter.Extension.class) @interface TestParameter { class Extension extends BaseParameterExtension { } } class DummyExtension implements Extension { } class BaseFieldExtension implements BeforeAllCallback, BeforeEachCallback { private final Class annotationType; @SuppressWarnings("unchecked") BaseFieldExtension() { Type genericSuperclass = getClass().getGenericSuperclass(); this.annotationType = (Class) ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0]; } @Override public final void beforeAll(ExtensionContext context) throws Exception { injectFields("beforeAll", context.getRequiredTestClass(), null, ReflectionUtils::isStatic); } @Override public final void beforeEach(ExtensionContext context) throws Exception { injectFields("beforeEach", context.getRequiredTestClass(), context.getRequiredTestInstance(), ReflectionUtils::isNotStatic); } private void injectFields(String trigger, Class testClass, Object instance, Predicate predicate) { findAnnotatedFields(testClass, this.annotationType, predicate).forEach(field -> { try { makeAccessible(field).set(instance, trigger + " - " + field.getName()); } catch (Throwable t) { ExceptionUtils.throwAsUncheckedException(t); } }); } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(MagicField.Extension.class) @interface MagicField { class Extension extends BaseFieldExtension { } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(InstanceField1.Extension.class) @interface InstanceField1 { class Extension extends BaseFieldExtension { } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) // Intentionally NOT annotated as follows // @ExtendWith(InstanceField2.Extension.class) @interface InstanceField2 { class Extension extends BaseFieldExtension { } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(StaticField1.Extension.class) @interface StaticField1 { class Extension extends BaseFieldExtension { } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) // Intentionally NOT annotated as follows // @ExtendWith(StaticField2.Extension.class) @interface StaticField2 { class Extension extends BaseFieldExtension { } } class ClassLevelExtension1 implements Extension { } class ClassLevelExtension2 implements Extension { } class InstanceLevelExtension1 implements Extension { } class InstanceLevelExtension2 implements Extension { } ExtensionRegistryTests.java000066400000000000000000000167221455764576500362010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.engine.extension.MutableExtensionRegistry.createRegistryFrom; import static org.junit.jupiter.engine.extension.MutableExtensionRegistry.createRegistryWithDefaultExtensions; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.engine.config.JupiterConfiguration; /** * Tests for the {@link MutableExtensionRegistry}. * * @since 5.0 */ class ExtensionRegistryTests { private static final int NUM_DEFAULT_EXTENSIONS = 6; private final JupiterConfiguration configuration = mock(); private MutableExtensionRegistry registry = createRegistryWithDefaultExtensions(configuration); @Test void newRegistryWithoutParentHasDefaultExtensions() { List extensions = registry.getExtensions(Extension.class); assertEquals(NUM_DEFAULT_EXTENSIONS, extensions.size()); assertDefaultGlobalExtensionsAreRegistered(); } @Test void newRegistryWithoutParentHasDefaultExtensionsPlusAutodetectedExtensionsLoadedViaServiceLoader() { when(configuration.isExtensionAutoDetectionEnabled()).thenReturn(true); registry = createRegistryWithDefaultExtensions(configuration); List extensions = registry.getExtensions(Extension.class); assertEquals(NUM_DEFAULT_EXTENSIONS + 1, extensions.size()); assertDefaultGlobalExtensionsAreRegistered(3); assertExtensionRegistered(registry, ServiceLoaderExtension.class); assertEquals(3, countExtensions(registry, BeforeAllCallback.class)); } @Test void registerExtensionByImplementingClass() { registry.registerExtension(MyExtension.class); assertExtensionRegistered(registry, MyExtension.class); registry.registerExtension(MyExtension.class); registry.registerExtension(MyExtension.class); registry.registerExtension(MyExtension.class); assertEquals(1, registry.getExtensions(MyExtension.class).size()); assertExtensionRegistered(registry, MyExtension.class); assertEquals(1, countExtensions(registry, MyExtensionApi.class)); registry.registerExtension(YourExtension.class); assertExtensionRegistered(registry, YourExtension.class); assertEquals(2, countExtensions(registry, MyExtensionApi.class)); } @Test void registerExtensionThatImplementsMultipleExtensionApis() { registry.registerExtension(MultipleExtension.class); assertExtensionRegistered(registry, MultipleExtension.class); assertEquals(1, countExtensions(registry, MyExtensionApi.class)); assertEquals(1, countExtensions(registry, AnotherExtensionApi.class)); } @Test void extensionsAreInheritedFromParent() { MutableExtensionRegistry parent = registry; parent.registerExtension(MyExtension.class); MutableExtensionRegistry child = createRegistryFrom(parent, Stream.of(YourExtension.class)); assertExtensionRegistered(child, MyExtension.class); assertExtensionRegistered(child, YourExtension.class); assertEquals(2, countExtensions(child, MyExtensionApi.class)); ExtensionRegistry grandChild = createRegistryFrom(child, Stream.empty()); assertExtensionRegistered(grandChild, MyExtension.class); assertExtensionRegistered(grandChild, YourExtension.class); assertEquals(2, countExtensions(grandChild, MyExtensionApi.class)); } @Test void registeringSameExtensionImplementationInParentAndChildDoesNotResultInDuplicate() { MutableExtensionRegistry parent = registry; parent.registerExtension(MyExtension.class); assertEquals(1, countExtensions(parent, MyExtensionApi.class)); MutableExtensionRegistry child = createRegistryFrom(parent, Stream.of(MyExtension.class, YourExtension.class)); assertExtensionRegistered(child, MyExtension.class); assertExtensionRegistered(child, YourExtension.class); assertEquals(2, countExtensions(child, MyExtensionApi.class)); ExtensionRegistry grandChild = createRegistryFrom(child, Stream.of(MyExtension.class, YourExtension.class)); assertExtensionRegistered(grandChild, MyExtension.class); assertExtensionRegistered(grandChild, YourExtension.class); assertEquals(2, countExtensions(grandChild, MyExtensionApi.class)); } @Test void canStreamOverRegisteredExtension() { registry.registerExtension(MyExtension.class); AtomicBoolean hasRun = new AtomicBoolean(false); registry.getExtensions(MyExtensionApi.class).forEach(extension -> { assertEquals(MyExtension.class.getName(), extension.getClass().getName()); hasRun.set(true); }); assertTrue(hasRun.get()); } private long countExtensions(ExtensionRegistry registry, Class extensionType) { return registry.stream(extensionType).count(); } private void assertExtensionRegistered(ExtensionRegistry registry, Class extensionType) { assertFalse(registry.getExtensions(extensionType).isEmpty(), () -> extensionType.getSimpleName() + " should be present"); } private void assertDefaultGlobalExtensionsAreRegistered() { assertDefaultGlobalExtensionsAreRegistered(2); } private void assertDefaultGlobalExtensionsAreRegistered(long bacCount) { assertExtensionRegistered(registry, DisabledCondition.class); assertExtensionRegistered(registry, TempDirectory.class); assertExtensionRegistered(registry, TimeoutExtension.class); assertExtensionRegistered(registry, RepeatedTestExtension.class); assertExtensionRegistered(registry, TestInfoParameterResolver.class); assertExtensionRegistered(registry, TestReporterParameterResolver.class); assertEquals(bacCount, countExtensions(registry, BeforeAllCallback.class)); assertEquals(2, countExtensions(registry, BeforeEachCallback.class)); assertEquals(3, countExtensions(registry, ParameterResolver.class)); assertEquals(1, countExtensions(registry, ExecutionCondition.class)); assertEquals(1, countExtensions(registry, TestTemplateInvocationContextProvider.class)); assertEquals(1, countExtensions(registry, InvocationInterceptor.class)); } // ------------------------------------------------------------------------- interface MyExtensionApi extends Extension { void doNothing(String test); } interface AnotherExtensionApi extends Extension { void doMore(); } static class MyExtension implements MyExtensionApi { @Override public void doNothing(String test) { } } static class YourExtension implements MyExtensionApi { @Override public void doNothing(String test) { } } static class MultipleExtension implements MyExtensionApi, AnotherExtensionApi { @Override public void doNothing(String test) { } @Override public void doMore() { } } } InvocationInterceptorTests.java000066400000000000000000000327471455764576500370310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Arrays; import java.util.EnumSet; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.extension.DynamicTestInvocationContext; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.testkit.engine.EngineExecutionResults; class InvocationInterceptorTests extends AbstractJupiterTestEngineTests { @Test void failsTestWhenInterceptorChainDoesNotCallInvocation() { var results = executeTestsForClass(InvocationIgnoringInterceptorTestCase.class); var tests = results.testEvents().assertStatistics(stats -> stats.failed(1).succeeded(0)); tests.failed().assertEventsMatchExactly( event(test("test"), finishedWithFailure(instanceOf(JUnitException.class), message(it -> it.startsWith("Chain of InvocationInterceptors never called invocation"))))); } static class InvocationIgnoringInterceptorTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) { // do nothing } }; @Test void test() { // never called } } @Test void successTestWhenInterceptorChainSkippedInvocation() { var results = executeTestsForClass(InvocationSkippedTestCase.class); results.testEvents().assertStatistics(stats -> stats.failed(0).succeeded(1)); } static class InvocationSkippedTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) { invocation.skip(); } }; @Test void test() { fail("should not be called"); } } @Test void failsTestWhenInterceptorChainCallsInvocationMoreThanOnce() { var results = executeTestsForClass(DoubleInvocationInterceptorTestCase.class); var tests = results.testEvents().assertStatistics(stats -> stats.failed(1).succeeded(0)); tests.failed().assertEventsMatchExactly( event(test("test"), finishedWithFailure(instanceOf(JUnitException.class), message(it -> it.startsWith( "Chain of InvocationInterceptors called invocation multiple times instead of just once"))))); } static class DoubleInvocationInterceptorTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); invocation.proceed(); } }; @Test void test() { // called twice } } @TestFactory Stream callsInterceptors() { var results = executeTestsForClass(TestCaseWithThreeInterceptors.class); results.testEvents().assertStatistics(stats -> stats.failed(0).succeeded(3)); return Arrays.stream(InvocationType.values()) // .map(invocationType -> dynamicTest(invocationType.name(), () -> { assertThat(getEvents(results, EnumSet.of(invocationType)).distinct()) // .containsExactly("before:foo", "before:bar", "before:baz", "test", "after:baz", "after:bar", "after:foo"); })); } private Stream getEvents(EngineExecutionResults results, EnumSet types) { return results.allEvents().reportingEntryPublished() // .map(event -> event.getPayload(ReportEntry.class).orElseThrow()) // .map(ReportEntry::getKeyValuePairs) // .filter(map -> map.keySet().stream().map(InvocationType::valueOf).anyMatch(types::contains)) // .flatMap(map -> map.values().stream()); } @ExtendWith({ FooInvocationInterceptor.class, BarInvocationInterceptor.class, BazInvocationInterceptor.class }) static class TestCaseWithThreeInterceptors { public TestCaseWithThreeInterceptors(TestReporter reporter) { publish(reporter, InvocationType.CONSTRUCTOR); } @BeforeAll static void beforeAll(TestReporter reporter) { publish(reporter, InvocationType.BEFORE_ALL); } @BeforeEach void beforeEach(TestReporter reporter) { publish(reporter, InvocationType.BEFORE_EACH); } @Test void test(TestReporter reporter) { publish(reporter, InvocationType.TEST_METHOD); } @RepeatedTest(1) void testTemplate(TestReporter reporter) { publish(reporter, InvocationType.TEST_TEMPLATE_METHOD); } @TestFactory DynamicTest testFactory(TestReporter reporter) { publish(reporter, InvocationType.TEST_FACTORY_METHOD); return dynamicTest("dynamicTest", () -> { publish(reporter, InvocationType.DYNAMIC_TEST); }); } @AfterEach void afterEach(TestReporter reporter) { publish(reporter, InvocationType.AFTER_EACH); } @AfterAll static void afterAll(TestReporter reporter) { publish(reporter, InvocationType.AFTER_ALL); } static void publish(TestReporter reporter, InvocationType type) { reporter.publishEntry(type.name(), "test"); } } enum InvocationType { BEFORE_ALL, CONSTRUCTOR, BEFORE_EACH, TEST_METHOD, TEST_TEMPLATE_METHOD, TEST_FACTORY_METHOD, DYNAMIC_TEST, AFTER_EACH, AFTER_ALL } abstract static class ReportingInvocationInterceptor implements InvocationInterceptor { private final Class testClass = TestCaseWithThreeInterceptors.class; private final String name; ReportingInvocationInterceptor(String name) { this.name = name; } @Override public void interceptBeforeAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).isEmpty(); assertEquals(testClass.getDeclaredMethod("beforeAll", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_ALL); } @Override public T interceptTestClassConstructor(Invocation invocation, ReflectiveInvocationContext> invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertEquals(testClass.getDeclaredConstructor(TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); return reportAndProceed(invocation, extensionContext, InvocationType.CONSTRUCTOR); } @Override public void interceptBeforeEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("beforeEach", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_EACH); } @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("test", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.TEST_METHOD); } @Override public void interceptTestTemplateMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("testTemplate", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.TEST_TEMPLATE_METHOD); } @Override public T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("testFactory", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); return reportAndProceed(invocation, extensionContext, InvocationType.TEST_FACTORY_METHOD); } @Override public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertThat(invocationContext.getExecutable()).isNotNull(); assertThat(extensionContext.getUniqueId()).isNotBlank(); assertThat(extensionContext.getElement()).isEmpty(); assertThat(extensionContext.getParent().flatMap(ExtensionContext::getTestMethod)).contains( testClass.getDeclaredMethod("testFactory", TestReporter.class)); reportAndProceed(invocation, extensionContext, InvocationType.DYNAMIC_TEST); } @Override public void interceptAfterEachMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("afterEach", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.AFTER_EACH); } @Override public void interceptAfterAllMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).isEmpty(); assertEquals(testClass.getDeclaredMethod("afterAll", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); reportAndProceed(invocation, extensionContext, InvocationType.AFTER_ALL); } private T reportAndProceed(Invocation invocation, ExtensionContext extensionContext, InvocationType type) throws Throwable { extensionContext.publishReportEntry(type.name(), "before:" + name); try { return invocation.proceed(); } finally { extensionContext.publishReportEntry(type.name(), "after:" + name); } } } static class FooInvocationInterceptor extends ReportingInvocationInterceptor { FooInvocationInterceptor() { super("foo"); } } static class BarInvocationInterceptor extends ReportingInvocationInterceptor { BarInvocationInterceptor() { super("bar"); } } static class BazInvocationInterceptor extends ReportingInvocationInterceptor { BazInvocationInterceptor() { super("baz"); } } } LifecycleMethodExecutionExceptionHandlerTests.java000066400000000000000000000510751455764576500425750ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.LifecycleMethodExecutionExceptionHandler; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Tests that verify the support for lifecycle method execution exception handling * via {@link LifecycleMethodExecutionExceptionHandler} * * @since 5.5 */ class LifecycleMethodExecutionExceptionHandlerTests extends AbstractJupiterTestEngineTests { private static List handlerCalls = new ArrayList<>(); private static boolean throwExceptionBeforeAll; private static boolean throwExceptionBeforeEach; private static boolean throwExceptionAfterEach; private static boolean throwExceptionAfterAll; @BeforeEach void resetStatics() { throwExceptionBeforeAll = true; throwExceptionBeforeEach = true; throwExceptionAfterEach = true; throwExceptionAfterAll = true; handlerCalls.clear(); SwallowExceptionHandler.beforeAllCalls = 0; SwallowExceptionHandler.beforeEachCalls = 0; SwallowExceptionHandler.afterEachCalls = 0; SwallowExceptionHandler.afterAllCalls = 0; RethrowExceptionHandler.beforeAllCalls = 0; RethrowExceptionHandler.beforeEachCalls = 0; RethrowExceptionHandler.afterEachCalls = 0; RethrowExceptionHandler.afterAllCalls = 0; ConvertExceptionHandler.beforeAllCalls = 0; ConvertExceptionHandler.beforeEachCalls = 0; ConvertExceptionHandler.afterEachCalls = 0; ConvertExceptionHandler.afterAllCalls = 0; UnrecoverableExceptionHandler.beforeAllCalls = 0; UnrecoverableExceptionHandler.beforeEachCalls = 0; UnrecoverableExceptionHandler.afterEachCalls = 0; UnrecoverableExceptionHandler.afterAllCalls = 0; ShouldNotBeCalledHandler.beforeAllCalls = 0; ShouldNotBeCalledHandler.beforeEachCalls = 0; ShouldNotBeCalledHandler.afterEachCalls = 0; ShouldNotBeCalledHandler.afterAllCalls = 0; } @Test void classLevelExceptionHandlersRethrowException() { LauncherDiscoveryRequest request = request().selectors(selectClass(RethrowingTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(1, RethrowExceptionHandler.beforeAllCalls, "Exception should handled in @BeforeAll"); assertEquals(1, RethrowExceptionHandler.afterAllCalls, "Exception should handled in @AfterAll"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(RethrowingTestCase.class), started()), // event(container(RethrowingTestCase.class), finishedWithFailure(instanceOf(RuntimeException.class))), // event(engine(), finishedSuccessfully())); } @Test void testLevelExceptionHandlersRethrowException() { throwExceptionBeforeAll = false; throwExceptionAfterAll = false; LauncherDiscoveryRequest request = request().selectors(selectClass(RethrowingTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(1, RethrowExceptionHandler.beforeEachCalls, "Exception should be handled in @BeforeEach"); assertEquals(1, RethrowExceptionHandler.afterEachCalls, "Exception should be handled in @AfterEach"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(RethrowingTestCase.class), started()), // event(test("aTest"), started()), // event(test("aTest"), finishedWithFailure(instanceOf(RuntimeException.class))), // event(container(RethrowingTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void classLevelExceptionHandlersConvertException() { LauncherDiscoveryRequest request = request().selectors(selectClass(ConvertingTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(1, ConvertExceptionHandler.beforeAllCalls, "Exception should handled in @BeforeAll"); assertEquals(1, ConvertExceptionHandler.afterAllCalls, "Exception should handled in @AfterAll"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ConvertingTestCase.class), started()), // event(container(ConvertingTestCase.class), finishedWithFailure(instanceOf(IOException.class))), // event(engine(), finishedSuccessfully())); } @Test void testLevelExceptionHandlersConvertException() { throwExceptionBeforeAll = false; throwExceptionAfterAll = false; LauncherDiscoveryRequest request = request().selectors(selectClass(ConvertingTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(1, ConvertExceptionHandler.beforeEachCalls, "Exception should be handled in @BeforeEach"); assertEquals(1, ConvertExceptionHandler.afterEachCalls, "Exception should be handled in @AfterEach"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ConvertingTestCase.class), started()), // event(test("aTest"), started()), // event(test("aTest"), finishedWithFailure(instanceOf(IOException.class))), // event(container(ConvertingTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void exceptionHandlersSwallowException() { LauncherDiscoveryRequest request = request().selectors(selectClass(SwallowingTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(1, SwallowExceptionHandler.beforeAllCalls, "Exception should be handled in @BeforeAll"); assertEquals(1, SwallowExceptionHandler.beforeEachCalls, "Exception should be handled in @BeforeEach"); assertEquals(1, SwallowExceptionHandler.afterEachCalls, "Exception should be handled in @AfterEach"); assertEquals(1, SwallowExceptionHandler.afterAllCalls, "Exception should be handled in @AfterAll"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(SwallowingTestCase.class), started()), // event(test("aTest"), started()), // event(test("aTest"), finishedSuccessfully()), // event(container(SwallowingTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void perClassLifecycleMethodsAreHandled() { LauncherDiscoveryRequest request = request().selectors(selectClass(PerClassLifecycleTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); assertEquals(2, SwallowExceptionHandler.beforeAllCalls, "Exception should be handled in @BeforeAll"); assertEquals(1, SwallowExceptionHandler.beforeEachCalls, "Exception should be handled in @BeforeEach"); assertEquals(1, SwallowExceptionHandler.afterEachCalls, "Exception should be handled in @AfterEach"); assertEquals(2, SwallowExceptionHandler.afterAllCalls, "Exception should be handled in @AfterAll"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(PerClassLifecycleTestCase.class), started()), // event(test("aTest"), started()), // event(test("aTest"), finishedSuccessfully()), // event(container(PerClassLifecycleTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void multipleHandlersAreCalledInOrder() { LauncherDiscoveryRequest request = request().selectors(selectClass(MultipleHandlersTestCase.class)).build(); EngineExecutionResults executionResults = executeTests(request); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(MultipleHandlersTestCase.class), started()), // event(test("aTest"), started()), // event(test("aTest"), finishedSuccessfully()), // event(test("aTest2"), started()), // event(test("aTest2"), finishedSuccessfully()), // event(container(MultipleHandlersTestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); // assertEquals(Arrays.asList( // BeforeAll chain (class level only) "RethrowExceptionBeforeAll", "SwallowExceptionBeforeAll", // BeforeEach chain for aTest (test + class level) "ConvertExceptionBeforeEach", "RethrowExceptionBeforeEach", "SwallowExceptionBeforeEach", // AfterEach chain for aTest (test + class level) "ConvertExceptionAfterEach", "RethrowExceptionAfterEach", "SwallowExceptionAfterEach", // BeforeEach chain for aTest2 (class level only) "RethrowExceptionBeforeEach", "SwallowExceptionBeforeEach", // AfterEach chain for aTest2 (class level only) "RethrowExceptionAfterEach", "SwallowExceptionAfterEach", // AfterAll chain (class level only) "RethrowExceptionAfterAll", "SwallowExceptionAfterAll" // ), handlerCalls, "Wrong order of handler calls"); } @Test void unrecoverableExceptionsAreNotPropagatedInBeforeAll() { throwExceptionBeforeAll = true; throwExceptionBeforeEach = false; throwExceptionAfterEach = false; throwExceptionAfterAll = false; boolean unrecoverableExceptionThrown = executeThrowingOutOfMemoryException(); assertTrue(unrecoverableExceptionThrown, "Unrecoverable Exception should be thrown"); assertEquals(1, UnrecoverableExceptionHandler.beforeAllCalls, "Exception should be handled in @BeforeAll"); assertEquals(0, ShouldNotBeCalledHandler.beforeAllCalls, "Exception should not propagate in @BeforeAll"); } @Test void unrecoverableExceptionsAreNotPropagatedInBeforeEach() { throwExceptionBeforeAll = false; throwExceptionBeforeEach = true; throwExceptionAfterEach = false; throwExceptionAfterAll = false; boolean unrecoverableExceptionThrown = executeThrowingOutOfMemoryException(); assertTrue(unrecoverableExceptionThrown, "Unrecoverable Exception should be thrown"); assertEquals(1, UnrecoverableExceptionHandler.beforeEachCalls, "Exception should be handled in @BeforeEach"); assertEquals(0, ShouldNotBeCalledHandler.beforeEachCalls, "Exception should not propagate in @BeforeEach"); } @Test void unrecoverableExceptionsAreNotPropagatedInAfterEach() { throwExceptionBeforeAll = false; throwExceptionBeforeEach = false; throwExceptionAfterEach = true; throwExceptionAfterAll = false; boolean unrecoverableExceptionThrown = executeThrowingOutOfMemoryException(); assertTrue(unrecoverableExceptionThrown, "Unrecoverable Exception should be thrown"); assertEquals(1, UnrecoverableExceptionHandler.afterEachCalls, "Exception should be handled in @AfterEach"); assertEquals(0, ShouldNotBeCalledHandler.afterEachCalls, "Exception should not propagate in @AfterEach"); } @Test void unrecoverableExceptionsAreNotPropagatedInAfterAll() { throwExceptionBeforeAll = false; throwExceptionBeforeEach = false; throwExceptionAfterEach = false; throwExceptionAfterAll = true; boolean unrecoverableExceptionThrown = executeThrowingOutOfMemoryException(); assertTrue(unrecoverableExceptionThrown, "Unrecoverable Exception should be thrown"); assertEquals(1, UnrecoverableExceptionHandler.afterAllCalls, "Exception should be handled in @AfterAll"); assertEquals(0, ShouldNotBeCalledHandler.afterAllCalls, "Exception should not propagate in @AfterAll"); } private boolean executeThrowingOutOfMemoryException() { LauncherDiscoveryRequest request = request().selectors( selectClass(UnrecoverableExceptionTestCase.class)).build(); try { executeTests(request); } catch (OutOfMemoryError expected) { return true; } return false; } // ------------------------------------------ static class BaseTestCase { @BeforeAll static void throwBeforeAll() { if (throwExceptionBeforeAll) { throw new RuntimeException("BeforeAllEx"); } } @BeforeEach void throwBeforeEach() { if (throwExceptionBeforeEach) { throw new RuntimeException("BeforeEachEx"); } } @Test void aTest() { } @AfterEach void throwAfterEach() { if (throwExceptionAfterEach) { throw new RuntimeException("AfterEachEx"); } } @AfterAll static void throwAfterAll() { if (throwExceptionAfterAll) { throw new RuntimeException("AfterAllEx"); } } } @ExtendWith(RethrowExceptionHandler.class) static class RethrowingTestCase extends BaseTestCase { } @ExtendWith(ConvertExceptionHandler.class) static class ConvertingTestCase extends BaseTestCase { } @ExtendWith(SwallowExceptionHandler.class) static class SwallowingTestCase extends BaseTestCase { } @ExtendWith(ShouldNotBeCalledHandler.class) @ExtendWith(UnrecoverableExceptionHandler.class) static class UnrecoverableExceptionTestCase extends BaseTestCase { } @ExtendWith(ShouldNotBeCalledHandler.class) @ExtendWith(SwallowExceptionHandler.class) @ExtendWith(RethrowExceptionHandler.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) static class MultipleHandlersTestCase extends BaseTestCase { @Override @ExtendWith(ConvertExceptionHandler.class) @Order(1) @Test void aTest() { } @Order(2) @Test void aTest2() { } } @ExtendWith(SwallowExceptionHandler.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) static class PerClassLifecycleTestCase extends BaseTestCase { @BeforeAll void beforeAll() { throw new RuntimeException("nonStaticBeforeAllEx"); } @AfterAll void afterAll() { throw new RuntimeException("nonStaticAfterAllEx"); } } // ------------------------------------------ static class RethrowExceptionHandler implements LifecycleMethodExecutionExceptionHandler { static int beforeAllCalls = 0; static int beforeEachCalls = 0; static int afterEachCalls = 0; static int afterAllCalls = 0; @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { beforeAllCalls++; handlerCalls.add("RethrowExceptionBeforeAll"); throw throwable; } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { beforeEachCalls++; handlerCalls.add("RethrowExceptionBeforeEach"); throw throwable; } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterEachCalls++; handlerCalls.add("RethrowExceptionAfterEach"); throw throwable; } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterAllCalls++; handlerCalls.add("RethrowExceptionAfterAll"); throw throwable; } } static class SwallowExceptionHandler implements LifecycleMethodExecutionExceptionHandler { static int beforeAllCalls = 0; static int beforeEachCalls = 0; static int afterEachCalls = 0; static int afterAllCalls = 0; @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) { beforeAllCalls++; handlerCalls.add("SwallowExceptionBeforeAll"); // Do not rethrow } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) { beforeEachCalls++; handlerCalls.add("SwallowExceptionBeforeEach"); // Do not rethrow } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) { afterEachCalls++; handlerCalls.add("SwallowExceptionAfterEach"); // Do not rethrow } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) { afterAllCalls++; handlerCalls.add("SwallowExceptionAfterAll"); // Do not rethrow } } static class ConvertExceptionHandler implements LifecycleMethodExecutionExceptionHandler { static int beforeAllCalls = 0; static int beforeEachCalls = 0; static int afterEachCalls = 0; static int afterAllCalls = 0; @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { beforeAllCalls++; handlerCalls.add("ConvertExceptionBeforeAll"); throw new IOException(throwable); } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { beforeEachCalls++; handlerCalls.add("ConvertExceptionBeforeEach"); throw new IOException(throwable); } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterEachCalls++; handlerCalls.add("ConvertExceptionAfterEach"); throw new IOException(throwable); } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterAllCalls++; handlerCalls.add("ConvertExceptionAfterAll"); throw new IOException(throwable); } } static class UnrecoverableExceptionHandler implements LifecycleMethodExecutionExceptionHandler { static int beforeAllCalls = 0; static int beforeEachCalls = 0; static int afterEachCalls = 0; static int afterAllCalls = 0; @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) { beforeAllCalls++; handlerCalls.add("UnrecoverableExceptionBeforeAll"); throw new OutOfMemoryError(); } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) { beforeEachCalls++; handlerCalls.add("UnrecoverableExceptionBeforeEach"); throw new OutOfMemoryError(); } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) { afterEachCalls++; handlerCalls.add("UnrecoverableExceptionAfterEach"); throw new OutOfMemoryError(); } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) { afterAllCalls++; handlerCalls.add("UnrecoverableExceptionAfterAll"); throw new OutOfMemoryError(); } } static class ShouldNotBeCalledHandler implements LifecycleMethodExecutionExceptionHandler { static int beforeAllCalls = 0; static int beforeEachCalls = 0; static int afterEachCalls = 0; static int afterAllCalls = 0; @Override public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { beforeAllCalls++; handlerCalls.add("ShouldNotBeCalledBeforeAll"); throw throwable; } @Override public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { ShouldNotBeCalledHandler.beforeEachCalls++; handlerCalls.add("ShouldNotBeCalledBeforeEach"); throw throwable; } @Override public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterEachCalls++; handlerCalls.add("ShouldNotBeCalledAfterEach"); throw throwable; } @Override public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { afterAllCalls++; handlerCalls.add("ShouldNotBeCalledAfterAll"); throw throwable; } } } OrderedClassTests.java000066400000000000000000000147361455764576500350510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestClassOrder; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; /** * Integration tests for {@link ClassOrderer} support. * * @since 5.8 */ class OrderedClassTests { private static final List callSequence = Collections.synchronizedList(new ArrayList<>()); @BeforeEach @AfterEach void clearCallSequence() { callSequence.clear(); } @Test void className() { executeTests(ClassOrderer.ClassName.class)// .assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("A_TestCase", "B_TestCase", "C_TestCase"); } @Test void classNameAcrossPackages() { try { example.B_TestCase.callSequence = callSequence; // @formatter:off executeTests(ClassOrderer.ClassName.class, selectClass(B_TestCase.class), selectClass(example.B_TestCase.class)) .assertStatistics(stats -> stats.succeeded(callSequence.size())); // @formatter:on assertThat(callSequence)// .containsExactly("example.B_TestCase", "B_TestCase"); } finally { example.B_TestCase.callSequence = null; } } @Test void displayName() { executeTests(ClassOrderer.DisplayName.class)// .assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("C_TestCase", "B_TestCase", "A_TestCase"); } @Test void orderAnnotation() { executeTests(ClassOrderer.OrderAnnotation.class)// .assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("A_TestCase", "C_TestCase", "B_TestCase"); } @Test void orderAnnotationOnNestedTestClassesWithGlobalConfig() { executeTests(ClassOrderer.OrderAnnotation.class, selectClass(OuterWithGlobalConfig.class))// .assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("Inner2", "Inner1", "Inner0", "Inner3"); } @Test @TrackLogRecords void orderAnnotationOnNestedTestClassesWithLocalConfig(LogRecordListener listener) { executeTests(ClassOrderer.class, selectClass(OuterWithLocalConfig.class))// .assertStatistics(stats -> stats.succeeded(callSequence.size())); // Ensure that supplying the ClassOrderer interface instead of an implementation // class results in a WARNING log message. This also lets us know the local // config is used. assertTrue(listener.stream(Level.WARNING)// .map(LogRecord::getMessage)// .anyMatch(m -> m.startsWith( "Failed to load default class orderer class 'org.junit.jupiter.api.ClassOrderer'"))); assertThat(callSequence)// .containsExactly("Inner2", "Inner1", "Inner1Inner1", "Inner1Inner0", "Inner0", "Inner3"); } @Test void random() { executeTests(ClassOrderer.Random.class)// .assertStatistics(stats -> stats.succeeded(callSequence.size())); } private Events executeTests(Class classOrderer) { return executeTests(classOrderer, selectClass(A_TestCase.class), selectClass(B_TestCase.class), selectClass(C_TestCase.class)); } private Events executeTests(Class classOrderer, DiscoverySelector... selectors) { // @formatter:off return EngineTestKit.engine("junit-jupiter") .configurationParameter(DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME, classOrderer.getName()) .selectors(selectors) .execute() .testEvents(); // @formatter:on } static abstract class BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { var testClass = testInfo.getTestClass().get(); callSequence.add(testClass.getSimpleName()); } @Test void a() { } } @Order(2) @DisplayName("Z") static class A_TestCase extends BaseTestCase { } static class B_TestCase extends BaseTestCase { } @Order(10) @DisplayName("A") static class C_TestCase extends BaseTestCase { } static class OuterWithGlobalConfig { @Nested class Inner0 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(2) class Inner1 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(1) class Inner2 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(Integer.MAX_VALUE) class Inner3 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } } @TestClassOrder(ClassOrderer.OrderAnnotation.class) static class OuterWithLocalConfig { @Nested class Inner0 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(2) class Inner1 { @Test void test() { callSequence.add(getClass().getSimpleName()); } @Nested @Order(2) class Inner1Inner0 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(1) class Inner1Inner1 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } } @Nested @Order(1) class Inner2 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } @Nested @Order(Integer.MAX_VALUE) class Inner3 { @Test void test() { callSequence.add(getClass().getSimpleName()); } } } } OrderedMethodTests.java000066400000000000000000000443641455764576500352240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.MethodOrderer.Random.RANDOM_SEED_PROPERTY_NAME; import static org.junit.jupiter.api.Order.DEFAULT; import static org.junit.jupiter.engine.Constants.DEFAULT_PARALLEL_EXECUTION_MODE; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.regex.Pattern; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodDescriptor; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.MethodOrderer.MethodName; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.MethodOrderer.Random; import org.junit.jupiter.api.MethodOrdererContext; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; import org.mockito.Mockito; /** * Integration tests that verify support for custom test method execution order * in the {@link JupiterTestEngine}. * * @since 5.4 */ class OrderedMethodTests { private static final Set callSequence = Collections.synchronizedSet(new LinkedHashSet<>()); private static final Set threadNames = Collections.synchronizedSet(new LinkedHashSet<>()); @BeforeEach void clearCallSequence() { callSequence.clear(); threadNames.clear(); } @Test void alphanumeric() { Class testClass = AlphanumericTestCase.class; // The name of the base class MUST start with a letter alphanumerically // greater than "A" so that BaseTestCase comes after AlphanumericTestCase // if methods are sorted by class name for the fallback ordering if two // methods have the same name but different parameter lists. Note, however, // that Alphanumeric actually does not order methods like that, but we want // this check to remain in place to ensure that the ordering does not rely // on the class names. assertThat(testClass.getSuperclass().getName()).isGreaterThan(testClass.getName()); var tests = executeTestsInParallel(testClass); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence).containsExactly("$()", "AAA()", "AAA(org.junit.jupiter.api.TestInfo)", "AAA(org.junit.jupiter.api.TestReporter)", "ZZ_Top()", "___()", "a1()", "a2()", "b()", "c()", "zzz()"); assertThat(threadNames).hasSize(1); } @Test void methodName() { Class testClass = MethodNameTestCase.class; // The name of the base class MUST start with a letter alphanumerically // greater than "A" so that BaseTestCase comes after AlphanumericTestCase // if methods are sorted by class name for the fallback ordering if two // methods have the same name but different parameter lists. Note, however, // that Alphanumeric actually does not order methods like that, but we want // this check to remain in place to ensure that the ordering does not rely // on the class names. assertThat(testClass.getSuperclass().getName()).isLessThan(testClass.getName()); var tests = executeTestsInParallel(testClass); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence).containsExactly("$()", "AAA()", "AAA(org.junit.jupiter.api.TestInfo)", "AAA(org.junit.jupiter.api.TestReporter)", "ZZ_Top()", "___()", "a1()", "a2()", "b()", "c()", "zzz()"); assertThat(threadNames).hasSize(1); } @Test void displayName() { var tests = executeTestsInParallel(DisplayNameTestCase.class); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("$", "AAA", "No_display_name_attribute_1_caps()", "No_display_name_attribute_2_caps()", "ZZ_Top", "___", "a1", "a2", "b()", "no_display_name_attribute_1()", "no_display_name_attribute_2()", "repetition 1 of 1", "⑦ϼ\uD83D\uDC69\u200D⚕\uD83E\uDDD8\u200D♂"); assertThat(threadNames).hasSize(1); } @Test void orderAnnotation() { assertOrderAnnotationSupport(OrderAnnotationTestCase.class); } @Test void orderAnnotationInNestedTestClass() { assertOrderAnnotationSupport(OuterTestCase.class); } @Test void orderAnnotationWithNestedTestClass() { var tests = executeTestsInParallel(OrderAnnotationWithNestedClassTestCase.class); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "nestedTest1", "nestedTest2"); assertThat(threadNames).hasSize(1); } private void assertOrderAnnotationSupport(Class testClass) { var tests = executeTestsInParallel(testClass); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// .containsExactly("test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8"); assertThat(threadNames).hasSize(1); } @Test void random() { var tests = executeTestsInParallel(RandomTestCase.class); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(threadNames).hasSize(1); } @Test void defaultOrderer() { var tests = executeTestsInParallel(WithoutTestMethodOrderTestCase.class, OrderAnnotation.class); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence).containsExactly("test1()", "test2()", "test3()"); assertThat(threadNames).hasSize(1); } @Test @TrackLogRecords void randomWithBogusSeedRepeatedly(LogRecordListener listener) { var seed = "explode"; var expectedMessagePattern = Pattern.compile( "Failed to convert configuration parameter \\[" + Pattern.quote(Random.RANDOM_SEED_PROPERTY_NAME) + "] with value \\[" + seed + "] to a long\\. Using default seed \\[\\d+] as fallback\\."); Set uniqueSequences = new HashSet<>(); for (var i = 0; i < 10; i++) { callSequence.clear(); listener.clear(); var tests = executeRandomTestCaseInParallelWithRandomSeed(seed); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); uniqueSequences.add(String.join(",", callSequence)); // @formatter:off assertThat(listener.stream(Random.class, Level.WARNING) .map(LogRecord::getMessage)) .anyMatch(expectedMessagePattern.asMatchPredicate()); // @formatter:on } assertThat(uniqueSequences).size().isEqualTo(1); } @Test @TrackLogRecords void randomWithDifferentSeedConsecutively(LogRecordListener listener) { Set uniqueSequences = new HashSet<>(); for (var i = 0; i < 10; i++) { var seed = String.valueOf(i); var expectedMessage = "Using custom seed for configuration parameter [" + Random.RANDOM_SEED_PROPERTY_NAME + "] with value [" + seed + "]."; callSequence.clear(); listener.clear(); var tests = executeRandomTestCaseInParallelWithRandomSeed(seed); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); uniqueSequences.add(String.join(",", callSequence)); // @formatter:off assertThat(listener.stream(Random.class, Level.CONFIG) .map(LogRecord::getMessage)) .contains(expectedMessage); // @formatter:on assertThat(threadNames).hasSize(i + 1); } // We assume that at least 3 out of 10 are different... assertThat(uniqueSequences).size().isGreaterThanOrEqualTo(3); } @Test @TrackLogRecords void randomWithCustomSeed(LogRecordListener listener) { var seed = "42"; var expectedMessage = "Using custom seed for configuration parameter [" + Random.RANDOM_SEED_PROPERTY_NAME + "] with value [" + seed + "]."; for (var i = 0; i < 10; i++) { callSequence.clear(); listener.clear(); var tests = executeRandomTestCaseInParallelWithRandomSeed(seed); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); // With a custom seed, the "randomness" must be the same for every iteration. assertThat(callSequence).containsExactly("test2()", "test3()", "test4()", "repetition 1 of 1", "test1()"); // @formatter:off assertThat(listener.stream(Random.class, Level.CONFIG) .map(LogRecord::getMessage)) .contains(expectedMessage); // @formatter:on } assertThat(threadNames).size().isGreaterThanOrEqualTo(3); } @Test @TrackLogRecords void misbehavingMethodOrdererThatAddsElements(LogRecordListener listener) { Class testClass = MisbehavingByAddingTestCase.class; executeTestsInParallel(testClass).assertStatistics(stats -> stats.succeeded(2)); assertThat(callSequence).containsExactlyInAnyOrder("test1()", "test2()"); var expectedMessage = "MethodOrderer [" + MisbehavingByAdding.class.getName() + "] added 2 MethodDescriptor(s) for test class [" + testClass.getName() + "] which will be ignored."; assertExpectedLogMessage(listener, expectedMessage); } @Test @TrackLogRecords void misbehavingMethodOrdererThatRemovesElements(LogRecordListener listener) { Class testClass = MisbehavingByRemovingTestCase.class; executeTestsInParallel(testClass).assertStatistics(stats -> stats.succeeded(3)); assertThat(callSequence).containsExactlyInAnyOrder("test1()", "test2()", "test3()"); var expectedMessage = "MethodOrderer [" + MisbehavingByRemoving.class.getName() + "] removed 2 MethodDescriptor(s) for test class [" + testClass.getName() + "] which will be retained with arbitrary ordering."; assertExpectedLogMessage(listener, expectedMessage); } private void assertExpectedLogMessage(LogRecordListener listener, String expectedMessage) { // @formatter:off assertThat(listener.stream(Level.WARNING) .map(LogRecord::getMessage)) .contains(expectedMessage); // @formatter:on } private Events executeTestsInParallel(Class testClass) { return executeTestsInParallel(testClass, Random.class); } private Events executeTestsInParallel(Class testClass, Class defaultOrderer) { // @formatter:off return EngineTestKit .engine("junit-jupiter") .configurationParameter(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true") .configurationParameter(DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent") .configurationParameter(DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME, defaultOrderer.getName()) .selectors(selectClass(testClass)) .execute() .testEvents(); // @formatter:on } private Events executeRandomTestCaseInParallelWithRandomSeed(String seed) { var configurationParameters = Map.of(// PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true", // DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent", // RANDOM_SEED_PROPERTY_NAME, seed // ); // @formatter:off return EngineTestKit .engine("junit-jupiter") .configurationParameters(configurationParameters) .selectors(selectClass(RandomTestCase.class)) .execute() .testEvents(); // @formatter:on } // ------------------------------------------------------------------------- static class BaseTestCase { @Test void AAA() { } @Test void c() { } } @SuppressWarnings("unused") @TestMethodOrder(MethodName.class) static class MethodNameTestCase extends BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { var method = testInfo.getTestMethod().orElseThrow(AssertionError::new); var signature = String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); callSequence.add(signature); threadNames.add(Thread.currentThread().getName()); } @TestFactory DynamicTest b() { return dynamicTest("dynamic", () -> { }); } @Test void $() { } @Test void ___() { } @Test void AAA(TestReporter testReporter) { } @Test void AAA(TestInfo testInfo) { } @Test void ZZ_Top() { } @Test void a1() { } @Test void a2() { } @RepeatedTest(1) void zzz() { } } @SuppressWarnings({ "deprecation", "unused" }) @TestMethodOrder(org.junit.jupiter.api.MethodOrderer.Alphanumeric.class) static class AlphanumericTestCase extends BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { var method = testInfo.getTestMethod().orElseThrow(AssertionError::new); var signature = String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); callSequence.add(signature); threadNames.add(Thread.currentThread().getName()); } @TestFactory DynamicTest b() { return dynamicTest("dynamic", () -> { }); } @Test void $() { } @Test void ___() { } @Test void AAA(TestReporter testReporter) { } @Test void AAA(TestInfo testInfo) { } @Test void ZZ_Top() { } @Test void a1() { } @Test void a2() { } @RepeatedTest(1) void zzz() { } } @TestMethodOrder(MethodOrderer.DisplayName.class) static class DisplayNameTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); threadNames.add(Thread.currentThread().getName()); } @TestFactory DynamicTest b() { return dynamicTest("dynamic", () -> { }); } @DisplayName("$") @Test void $() { } @DisplayName("___") @Test void ___() { } @DisplayName("AAA") @Test void AAA() { } @DisplayName("ZZ_Top") @Test void ZZ_Top() { } @DisplayName("a1") @Test void a1() { } @DisplayName("a2") @Test void a2() { } @DisplayName("zzz") @RepeatedTest(1) void zzz() { } @Test @DisplayName("⑦ϼ\uD83D\uDC69\u200D⚕\uD83E\uDDD8\u200D♂") void special_characters() { } @Test void no_display_name_attribute_1() { } @Test void no_display_name_attribute_2() { } @Test void No_display_name_attribute_1_caps() { } @Test void No_display_name_attribute_2_caps() { } } @TestMethodOrder(OrderAnnotation.class) static class OrderAnnotationTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); threadNames.add(Thread.currentThread().getName()); } @Test @DisplayName("test8") @Order(Integer.MAX_VALUE) void maxInteger() { } @Test @DisplayName("test7") @Order(DEFAULT + 1) void defaultOrderValuePlusOne() { } @Test @DisplayName("test6") // @Order(DEFAULT) void defaultOrderValue() { } @Test @DisplayName("test3") @Order(3) void $() { } @Test @DisplayName("test5") @Order(5) void AAA() { } @TestFactory @DisplayName("test4") @Order(4) DynamicTest aaa() { return dynamicTest("test4", () -> { }); } @Test @DisplayName("test1") @Order(1) void zzz() { } @RepeatedTest(value = 1, name = "{displayName}") @DisplayName("test2") @Order(2) void ___() { } } static class OuterTestCase { @Nested class NestedOrderAnnotationTestCase extends OrderAnnotationTestCase { } } @TestMethodOrder(Random.class) static class RandomTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); threadNames.add(Thread.currentThread().getName()); } @Test void test1() { } @Test void test2() { } @Test void test3() { } @TestFactory DynamicTest test4() { return dynamicTest("dynamic", () -> { }); } @RepeatedTest(1) void test5() { } } @TestMethodOrder(MisbehavingByAdding.class) static class MisbehavingByAddingTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); } @Test void test1() { } @Test void test2() { } } @TestMethodOrder(MisbehavingByRemoving.class) static class MisbehavingByRemovingTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); } @Test void test1() { } @Test void test2() { } @Test void test3() { } } static class OrderAnnotationWithNestedClassTestCase extends OrderAnnotationTestCase { @Nested @TestMethodOrder(OrderAnnotation.class) class NestedTests { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); } @Test @Order(1) @DisplayName("nestedTest1") void nestedTest1() { } @Test @Order(2) @DisplayName("nestedTest2") void nestedTest2() { } } } static class MisbehavingByAdding implements MethodOrderer { @Override public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().add(mockMethodDescriptor()); context.getMethodDescriptors().add(mockMethodDescriptor()); } @SuppressWarnings("unchecked") static T mockMethodDescriptor() { return (T) Mockito.mock((Class) MethodDescriptor.class); } } static class MisbehavingByRemoving implements MethodOrderer { @Override public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().remove(0); context.getMethodDescriptors().remove(0); } } static class WithoutTestMethodOrderTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { callSequence.add(testInfo.getDisplayName()); threadNames.add(Thread.currentThread().getName()); } @Test @Order(2) void test2() { } @Test @Order(3) void test3() { } @Test @Order(1) void test1() { } } } OrderedProgrammaticExtensionRegistrationTests.java000066400000000000000000000215061455764576500427120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Order.DEFAULT; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; /** * Integration tests that verify support for {@linkplain Order ordered} programmatic * extension registration via {@link RegisterExtension @RegisterExtension} in the * {@link JupiterTestEngine}. * * @since 5.4 * @see ProgrammaticExtensionRegistrationTests */ class OrderedProgrammaticExtensionRegistrationTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); /** * This method basically verifies the implementation of * {@link java.lang.String#hashCode()} (which needn't really be tested) * in order to make reasonable assumptions about how fields are sorted * in {@link org.junit.platform.commons.util.ReflectionUtils#defaultFieldSorter(Field, Field)}. * *

In other words, this method is just a sanity check for the chosen * field names in the test cases used in these tests. */ @BeforeAll static void assertAssumptionsAboutDefaultOrderingAlgorithm() { String fieldName1 = "extension1"; String fieldName2 = "extension2"; String fieldName3 = "extension3"; assertThat(fieldName1.hashCode()).isLessThan(fieldName2.hashCode()); assertThat(fieldName2.hashCode()).isLessThan(fieldName3.hashCode()); } @BeforeEach void clearCallSequence() { callSequence.clear(); } @Test void instanceLevelWithDefaultOrder() { assertOutcome(DefaultOrderInstanceLevelExtensionRegistrationTestCase.class, 1, 2, 3); } @Test void instanceLevelWithExplicitOrder() { assertOutcome(ExplicitOrderInstanceLevelExtensionRegistrationTestCase.class, 3, 2, 1); } @Test void instanceLevelWithDefaultOrderAndExplicitOrder() { assertOutcome(DefaultOrderAndExplicitOrderInstanceLevelExtensionRegistrationTestCase.class, 3, 1, 2); } /** * Verify that an "after" callback can be registered first relative to other * non-annotated "after" callbacks. * * @since 5.6 * @see gh-1924 */ @Test void instanceLevelWithDefaultOrderPlusOneAndDefaultOrder() { assertOutcome(DefaultOrderPlusOneAndDefaultOrderInstanceLevelExtensionRegistrationTestCase.class, 1, 3, 2); } @Test void instanceLevelWithDefaultOrderAndExplicitOrderWithTestInstancePerClassLifecycle() { assertOutcome( DefaultOrderAndExplicitOrderInstanceLevelExtensionRegistrationWithTestInstancePerClassLifecycleTestCase.class, 3, 1, 2); } @Test void classLevelWithDefaultOrderAndExplicitOrder() { assertOutcome(DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase.class, 3, 1, 2); } @Test void classLevelWithDefaultOrderAndExplicitOrderInheritedFromSuperclass() { assertOutcome(InheritedDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase.class, 3, 1, 2); } @Test void classLevelWithDefaultOrderShadowingOrderFromSuperclass() { assertOutcome(DefaultOrderShadowingDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase.class, 1, 2, 3); } @Test void classLevelWithExplicitOrderShadowingOrderFromSuperclass() { assertOutcome(ExplicitOrderShadowingDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase.class, 3, 2, 1); } @Test void classLevelWithDefaultOrderAndExplicitOrderFromInterface() { assertOutcome(DefaultOrderAndExplicitOrderExtensionRegistrationFromInterfaceTestCase.class, 3, 1, 2); } private void assertOutcome(Class testClass, Integer... values) { executeTestsForClass(testClass).testEvents().assertStatistics(stats -> stats.succeeded(1)); assertThat(callSequence).containsExactly(values); } // ------------------------------------------------------------------- private static class AbstractTestCase { @Test void test() { } } static class DefaultOrderInstanceLevelExtensionRegistrationTestCase extends AbstractTestCase { @RegisterExtension Extension extension1 = new BeforeEachExtension(1); @RegisterExtension Extension extension3 = new BeforeEachExtension(3); @RegisterExtension Extension extension2 = new BeforeEachExtension(2); } static class ExplicitOrderInstanceLevelExtensionRegistrationTestCase extends AbstractTestCase { @Order(3) @RegisterExtension Extension extension1 = new BeforeEachExtension(1); @Order(2) @RegisterExtension Extension extension2 = new BeforeEachExtension(2); @Order(1) @RegisterExtension Extension extension3 = new BeforeEachExtension(3); } static class DefaultOrderAndExplicitOrderInstanceLevelExtensionRegistrationTestCase extends AbstractTestCase { // @Order(3) @RegisterExtension Extension extension1 = new BeforeEachExtension(1); // @Order(2) @RegisterExtension Extension extension2 = new BeforeEachExtension(2); @Order(1) @RegisterExtension Extension extension3 = new BeforeEachExtension(3); } static class DefaultOrderPlusOneAndDefaultOrderInstanceLevelExtensionRegistrationTestCase extends AbstractTestCase { @Order(DEFAULT + 1) @RegisterExtension Extension extension1 = new AfterEachExtension(1); @RegisterExtension Extension extension2 = new AfterEachExtension(2); @RegisterExtension Extension extension3 = new AfterEachExtension(3); } @TestInstance(PER_CLASS) static class DefaultOrderAndExplicitOrderInstanceLevelExtensionRegistrationWithTestInstancePerClassLifecycleTestCase extends AbstractTestCase { // @Order(3) @RegisterExtension Extension extension1 = new BeforeEachExtension(1); // @Order(2) @RegisterExtension Extension extension2 = new BeforeEachExtension(2); @Order(1) @RegisterExtension Extension extension3 = new BeforeEachExtension(3); } static class DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase extends AbstractTestCase { // @Order(3) @RegisterExtension static Extension extension1 = new BeforeEachExtension(1); // @Order(2) @RegisterExtension static Extension extension2 = new BeforeEachExtension(2); @Order(1) @RegisterExtension static Extension extension3 = new BeforeEachExtension(3); } static class InheritedDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase extends DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase { } static class DefaultOrderShadowingDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase extends DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase { // @Order(1) @RegisterExtension static Extension extension3 = new BeforeEachExtension(3); } static class ExplicitOrderShadowingDefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase extends DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationTestCase { @Order(2) @RegisterExtension static Extension extension2 = new BeforeEachExtension(2); } interface DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationInterface { // @Order(3) @RegisterExtension static Extension extension1 = new BeforeEachExtension(1); // @Order(2) @RegisterExtension static Extension extension2 = new BeforeEachExtension(2); @Order(1) @RegisterExtension static Extension extension3 = new BeforeEachExtension(3); } static class DefaultOrderAndExplicitOrderExtensionRegistrationFromInterfaceTestCase extends AbstractTestCase implements DefaultOrderAndExplicitOrderClassLevelExtensionRegistrationInterface { } private static class BeforeEachExtension implements BeforeEachCallback { private final int id; BeforeEachExtension(int id) { this.id = id; } @Override public void beforeEach(ExtensionContext context) { callSequence.add(this.id); } } private static class AfterEachExtension implements AfterEachCallback { private final int id; AfterEachExtension(int id) { this.id = id; } @Override public void afterEach(ExtensionContext context) { callSequence.add(this.id); } } } ParameterResolverTests.java000066400000000000000000000430661455764576500361370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.function.Predicate; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.engine.execution.injection.sample.CustomAnnotation; import org.junit.jupiter.engine.execution.injection.sample.CustomAnnotationParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.CustomType; import org.junit.jupiter.engine.execution.injection.sample.CustomTypeParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.MapOfListsTypeBasedParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.MapOfStringsParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.NullIntegerParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.NumberParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.PrimitiveArrayParameterResolver; import org.junit.jupiter.engine.execution.injection.sample.PrimitiveIntegerParameterResolver; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests that verify support for {@link ParameterResolver} * extensions in the {@link JupiterTestEngine}. * * @since 5.0 */ class ParameterResolverTests extends AbstractJupiterTestEngineTests { @Test void constructorInjection() { EngineExecutionResults executionResults = executeTestsForClass(ConstructorInjectionTestCase.class); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void constructorInjectionWithAnnotatedParameter() { EngineExecutionResults executionResults = executeTestsForClass( AnnotatedParameterConstructorInjectionTestCase.class); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass(MethodInjectionTestCase.class); assertEquals(7, executionResults.testEvents().started().count(), "# tests started"); assertEquals(6, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForNullValuedMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass(NullMethodInjectionTestCase.class); Events tests = executionResults.testEvents(); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off Predicate expectations = s -> s.contains("NullIntegerParameterResolver") && s.contains("resolved a null value for parameter") && s.contains("but a primitive of type [int] is required"); tests.failed().assertEventsMatchExactly( event( test("injectPrimitive"), finishedWithFailure(instanceOf(ParameterResolutionException.class), message(expectations)) )); // @formatter:on } @Test void executeTestsForPrimitiveIntegerMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass(PrimitiveIntegerMethodInjectionTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForPrimitiveArrayMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass(PrimitiveArrayMethodInjectionTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForPotentiallyIncompatibleTypeMethodInjectionCases() { EngineExecutionResults executionResults = executeTestsForClass( PotentiallyIncompatibleTypeMethodInjectionTestCase.class); Events tests = executionResults.testEvents(); assertEquals(3, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests failed"); // @formatter:off Predicate expectations = s -> s.contains("NumberParameterResolver") && s.contains("resolved a value of type [java.lang.Integer]") && s.contains("but a value assignment compatible with [java.lang.Double] is required"); tests.failed().assertEventsMatchExactly( event( test("doubleParameterInjection"), finishedWithFailure(instanceOf(ParameterResolutionException.class), message(expectations) ))); // @formatter:on } @Test void executeTestsForMethodInjectionInBeforeAndAfterEachMethods() { EngineExecutionResults executionResults = executeTestsForClass(BeforeAndAfterMethodInjectionTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForMethodInjectionInBeforeAndAfterAllMethods() { EngineExecutionResults executionResults = executeTestsForClass(BeforeAndAfterAllMethodInjectionTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForMethodWithExtendWithAnnotation() { EngineExecutionResults executionResults = executeTestsForClass(ExtendWithOnMethodTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } @Test void executeTestsForParameterizedTypesSelectingByClass() { assertEventsForParameterizedTypes(executeTestsForClass(ParameterizedTypeTestCase.class)); } @Test void executeTestsForParameterizedTypesSelectingByFullyQualifiedMethodName() { String fqmn = ReflectionUtils.getFullyQualifiedMethodName(ParameterizedTypeTestCase.class, "testMapOfStrings", Map.class); assertEventsForParameterizedTypes(executeTests(selectMethod(fqmn))); } @Test void executeTestsForTypeBasedParameterResolverTestCaseSelectingByClass() { assertEventsForParameterizedTypes(executeTestsForClass(TypeBasedParameterResolverTestCase.class)); } @Test void executeTestsForTypeBasedParameterResolverTestCaseSelectingByFullyQualifiedMethodName() { String fqmn = ReflectionUtils.getFullyQualifiedMethodName(TypeBasedParameterResolverTestCase.class, "testMapOfLists", Map.class); assertEventsForParameterizedTypes(executeTests(selectMethod(fqmn))); } @Disabled("Disabled until a decision has been made regarding #956") @Test void executeTestsForParameterizedTypesSelectingByFullyQualifiedMethodNameContainingGenericInfo() throws Exception { Method method = ParameterizedTypeTestCase.class.getDeclaredMethod("testMapOfStrings", Map.class); String genericParameterTypeName = method.getGenericParameterTypes()[0].getTypeName(); String fqmn = String.format("%s#%s(%s)", ParameterizedTypeTestCase.class.getName(), "testMapOfStrings", genericParameterTypeName); assertEventsForParameterizedTypes(executeTests(selectMethod(fqmn))); } private void assertEventsForParameterizedTypes(EngineExecutionResults executionResults) { assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); assertEquals(0, executionResults.testEvents().skipped().count(), "# tests skipped"); assertEquals(0, executionResults.testEvents().aborted().count(), "# tests aborted"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests failed"); } // ------------------------------------------------------------------- @ExtendWith(CustomTypeParameterResolver.class) static class ConstructorInjectionTestCase { private final TestInfo outerTestInfo; private final CustomType outerCustomType; ConstructorInjectionTestCase(TestInfo testInfo, CustomType customType) { this.outerTestInfo = testInfo; this.outerCustomType = customType; } @Test void test() { assertNotNull(this.outerTestInfo); assertNotNull(this.outerCustomType); } @Nested class NestedTestCase { private final TestInfo innerTestInfo; private final CustomType innerCustomType; NestedTestCase(TestInfo testInfo, CustomType customType) { this.innerTestInfo = testInfo; this.innerCustomType = customType; } @Test void test() { assertNotNull(outerTestInfo); assertNotNull(outerCustomType); assertNotNull(this.innerTestInfo); assertNotNull(this.innerCustomType); } } } @ExtendWith(CustomAnnotationParameterResolver.class) static class AnnotatedParameterConstructorInjectionTestCase { private final TestInfo outerTestInfo; private final CustomType outerCustomType; AnnotatedParameterConstructorInjectionTestCase(TestInfo testInfo, @CustomAnnotation CustomType customType) { this.outerTestInfo = testInfo; this.outerCustomType = customType; } @Test void test() { assertNotNull(this.outerTestInfo); assertNotNull(this.outerCustomType); } @Nested // See https://github.com/junit-team/junit5/issues/1345 class AnnotatedConstructorParameterNestedTestCase { private final TestInfo innerTestInfo; private final CustomType innerCustomType; AnnotatedConstructorParameterNestedTestCase(TestInfo testInfo, @CustomAnnotation CustomType customType) { this.innerTestInfo = testInfo; this.innerCustomType = customType; } @Test void test() { assertNotNull(outerTestInfo); assertNotNull(outerCustomType); assertNotNull(this.innerTestInfo); assertNotNull(this.innerCustomType); } } } @ExtendWith({ CustomTypeParameterResolver.class, CustomAnnotationParameterResolver.class }) static class MethodInjectionTestCase { @Test void parameterInjectionOfTestInfo(TestInfo testInfo) { assertNotNull(testInfo); } @Test void parameterInjectionWithCompetingResolversFail(@CustomAnnotation CustomType customType) { // should fail } @Test void parameterInjectionByType(CustomType customType) { assertNotNull(customType); } @Test void parameterInjectionByAnnotation(@CustomAnnotation String value) { assertNotNull(value); } // some overloaded methods @Test void overloadedName() { assertTrue(true); } @Test void overloadedName(CustomType customType) { assertNotNull(customType); } @Test void overloadedName(CustomType customType, @CustomAnnotation String value) { assertNotNull(customType); assertNotNull(value); } } @ExtendWith(NullIntegerParameterResolver.class) static class NullMethodInjectionTestCase { @Test void injectWrapper(Integer number) { assertNull(number); } @Test void injectPrimitive(int number) { // should never be invoked since an int cannot be null } } @ExtendWith(PrimitiveIntegerParameterResolver.class) static class PrimitiveIntegerMethodInjectionTestCase { @Test void intPrimitive(int i) { assertEquals(42, i); } } @ExtendWith(PrimitiveArrayParameterResolver.class) static class PrimitiveArrayMethodInjectionTestCase { @Test void primitiveArray(int... ints) { assertArrayEquals(new int[] { 1, 2, 3 }, ints); } } @ExtendWith(NumberParameterResolver.class) static class PotentiallyIncompatibleTypeMethodInjectionTestCase { @Test void numberParameterInjection(Number number) { assertEquals(Integer.valueOf(42), number); } @Test void integerParameterInjection(Integer number) { assertEquals(Integer.valueOf(42), number); } /** * This test must fail, since {@link Double} is a {@link Number} but not an {@link Integer}. * @see NumberParameterResolver */ @Test void doubleParameterInjection(Double number) { /* no-op */ } } static class BeforeAndAfterMethodInjectionTestCase { @BeforeEach void before(TestInfo testInfo) { assertEquals("custom name", testInfo.getDisplayName()); } @Test @DisplayName("custom name") void customNamedTest() { } @AfterEach void after(TestInfo testInfo) { assertEquals("custom name", testInfo.getDisplayName()); } } @DisplayName("custom class name") static class BeforeAndAfterAllMethodInjectionTestCase { @BeforeAll static void beforeAll(TestInfo testInfo) { assertEquals("custom class name", testInfo.getDisplayName()); } @Test void aTest() { } @AfterAll static void afterAll(TestInfo testInfo) { assertEquals("custom class name", testInfo.getDisplayName()); } } static class ExtendWithOnMethodTestCase { /** * This set-up / tear-down method is here to verify that {@code @BeforeEach} * and {@code @AfterEach} methods are properly invoked using the same * {@code ExtensionRegistry} as the one used for the corresponding * {@code @Test} method. * * @see #523 */ @BeforeEach @AfterEach void setUpAndTearDown(CustomType customType, @CustomAnnotation String value) { assertNotNull(customType); assertNotNull(value); } @Test @ExtendWith(CustomTypeParameterResolver.class) @ExtendWith(CustomAnnotationParameterResolver.class) void testMethodWithExtensionAnnotation(CustomType customType, @CustomAnnotation String value) { assertNotNull(customType); assertNotNull(value); } } static class ParameterizedTypeTestCase { @Test @ExtendWith(MapOfStringsParameterResolver.class) void testMapOfStrings(Map map) { assertNotNull(map); assertEquals("value", map.get("key")); } } static class TypeBasedParameterResolverTestCase { @Test @ExtendWith(MapOfListsTypeBasedParameterResolver.class) void testMapOfLists(Map> map) { assertNotNull(map); assertEquals(asList(1, 42), map.get("ids")); } } } ProgrammaticExtensionRegistrationTests.java000066400000000000000000000527661455764576500414210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.allOf; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.cause; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.engine.execution.injection.sample.LongParameterResolver; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for programmatic extension registration * via {@link RegisterExtension @RegisterExtension} in the {@link JupiterTestEngine}. * * @since 5.1 * @see OrderedProgrammaticExtensionRegistrationTests */ class ProgrammaticExtensionRegistrationTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @Test void instanceLevel() { assertOneTestSucceeded(InstanceLevelExtensionRegistrationTestCase.class); } @Test void instanceLevelWithInjectedExtension() { assertOneTestSucceeded(InstanceLevelExtensionRegistrationWithInjectedExtensionTestCase.class); } @Test void instanceLevelWithTestInstancePerClassLifecycle() { assertOneTestSucceeded(InstanceLevelExtensionRegistrationWithTestInstancePerClassLifecycleTestCase.class); } @Test void classLevel() { assertOneTestSucceeded(ClassLevelExtensionRegistrationTestCase.class); } @Test void classLevelFromSuperclass() { assertOneTestSucceeded(SubClassLevelExtensionRegistrationTestCase.class); } @Test void classLevelFromInterface() { assertOneTestSucceeded(ExtensionRegistrationFromInterfaceTestCase.class); } @Test void instanceLevelWithInheritedAndHiddenExtensions() { callSequence.clear(); Class testClass = InstanceLevelExtensionRegistrationParentTestCase.class; String parent = testClass.getSimpleName(); assertOneTestSucceeded(testClass); assertThat(callSequence).containsExactly( // parent + " :: extension1: before test", // parent + " :: extension2: before test" // ); callSequence.clear(); testClass = InstanceLevelExtensionRegistrationChildTestCase.class; String child = testClass.getSimpleName(); assertOneTestSucceeded(testClass); assertThat(callSequence).containsExactly( // parent + " :: extension1: before test", // child + " :: extension2: before test", // child + " :: extension3: before test" // ); } @Test void classLevelWithInheritedAndHiddenExtensions() { callSequence.clear(); Class testClass = ClassLevelExtensionRegistrationParentTestCase.class; String parent = testClass.getSimpleName(); assertOneTestSucceeded(testClass); assertThat(callSequence).containsExactly( // parent + " :: extension1: before test", // parent + " :: extension2: before test" // ); callSequence.clear(); testClass = ClassLevelExtensionRegistrationChildTestCase.class; String child = testClass.getSimpleName(); assertOneTestSucceeded(testClass); assertThat(callSequence).containsExactly( // parent + " :: extension1: before test", // child + " :: extension2: before test", // child + " :: extension3: before test" // ); } /** * @since 5.5 */ @Test void instanceLevelWithFieldThatDoesNotImplementAnExtensionApi() { callSequence.clear(); assertOneTestSucceeded(InstanceLevelCustomExtensionApiTestCase.class); assertThat(callSequence).containsExactly( // CustomExtensionImpl.class.getSimpleName() + " :: before test", // CustomExtensionImpl.class.getSimpleName() + " :: doSomething()" // ); } /** * @since 5.5 */ @Test void classLevelWithFieldThatDoesNotImplementAnExtensionApi() { callSequence.clear(); assertOneTestSucceeded(ClassLevelCustomExtensionApiTestCase.class); assertThat(callSequence).containsExactly( // CustomExtensionImpl.class.getSimpleName() + " :: before test", // CustomExtensionImpl.class.getSimpleName() + " :: doSomething()" // ); } /** * @since 5.5 */ @Test void instanceLevelWithPrivateField() { Class testClass = InstanceLevelExtensionRegistrationWithPrivateFieldTestCase.class; executeTestsForClass(testClass).testEvents().assertStatistics(stats -> stats.succeeded(1)); } /** * @since 5.5 */ @Test void classLevelWithPrivateField() { Class testClass = ClassLevelExtensionRegistrationWithPrivateFieldTestCase.class; executeTestsForClass(testClass).testEvents().assertStatistics(stats -> stats.succeeded(1)); } @Test void instanceLevelWithNullField() { Class testClass = InstanceLevelExtensionRegistrationWithNullFieldTestCase.class; executeTestsForClass(testClass).testEvents().assertThatEvents().haveExactly(1, finishedWithFailure( instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, null)))); } @Test void classLevelWithNullField() { Class testClass = ClassLevelExtensionRegistrationWithNullFieldTestCase.class; executeTestsForClass(testClass).containerEvents().assertThatEvents().haveExactly(1, finishedWithFailure( instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, null)))); } /** * @since 5.5 */ @Test void instanceLevelWithNonExtensionFieldValue() { Class testClass = InstanceLevelExtensionRegistrationWithNonExtensionFieldValueTestCase.class; executeTestsForClass(testClass).testEvents().assertThatEvents().haveExactly(1, finishedWithFailure( instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, String.class)))); } /** * @since 5.5 */ @Test void classLevelWithNonExtensionFieldValue() { Class testClass = ClassLevelExtensionRegistrationWithNonExtensionFieldValueTestCase.class; executeTestsForClass(testClass).containerEvents().assertThatEvents().haveExactly(1, finishedWithFailure( instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, String.class)))); } private String expectedMessage(Class testClass, Class valueType) { return "Failed to register extension via @RegisterExtension field [" + field(testClass) + "]: field value's type [" + (valueType != null ? valueType.getName() : null) + "] must implement an [" + Extension.class.getName() + "] API."; } private Field field(Class testClass) { try { return testClass.getDeclaredField("extension"); } catch (Exception ex) { throw new RuntimeException(ex); } } @Test void propagatesCheckedExceptionThrownDuringInitializationOfStaticField() { assertClassFails(ClassLevelExplosiveCheckedExceptionTestCase.class, allOf(instanceOf(ExceptionInInitializerError.class), cause(instanceOf(Exception.class), message("boom")))); } @Test void propagatesUncheckedExceptionThrownDuringInitializationOfStaticField() { assertClassFails(ClassLevelExplosiveUncheckedExceptionTestCase.class, allOf( instanceOf(ExceptionInInitializerError.class), cause(instanceOf(RuntimeException.class), message("boom")))); } @Test void propagatesErrorThrownDuringInitializationOfStaticField() { assertClassFails(ClassLevelExplosiveErrorTestCase.class, allOf(instanceOf(Error.class), message("boom"))); } @Test void propagatesCheckedExceptionThrownDuringInitializationOfInstanceField() { assertTestFails(InstanceLevelExplosiveCheckedExceptionTestCase.class, allOf(instanceOf(Exception.class), message("boom"))); } @Test void propagatesUncheckedExceptionThrownDuringInitializationOfInstanceField() { assertTestFails(InstanceLevelExplosiveUncheckedExceptionTestCase.class, allOf(instanceOf(RuntimeException.class), message("boom"))); } @Test void propagatesErrorThrownDuringInitializationOfInstanceField() { assertTestFails(InstanceLevelExplosiveErrorTestCase.class, allOf(instanceOf(Error.class), message("boom"))); } @Test void storesExtensionInRegistryOfNestedTestMethods() { var results = executeTestsForClass(TwoNestedClassesTestCase.class); results.testEvents().assertStatistics(stats -> stats.succeeded(4)); } private void assertClassFails(Class testClass, Condition causeCondition) { EngineExecutionResults executionResults = executeTestsForClass(testClass); executionResults.containerEvents().assertThatEvents().haveExactly(1, finishedWithFailure(causeCondition)); } private void assertTestFails(Class testClass, Condition causeCondition) { executeTestsForClass(testClass).testEvents().assertThatEvents().haveExactly(1, finishedWithFailure(causeCondition)); } private void assertOneTestSucceeded(Class testClass) { executeTestsForClass(testClass).testEvents().assertStatistics( stats -> stats.started(1).succeeded(1).skipped(0).aborted(0).failed(0)); } // ------------------------------------------------------------------- private static void assertWisdom(CrystalBall crystalBall, String wisdom, String useCase) { assertNotNull(crystalBall, useCase); assertEquals("Outlook good", wisdom, useCase); } static class InstanceLevelExtensionRegistrationTestCase { @RegisterExtension final CrystalBall crystalBall = new CrystalBall("Outlook good"); @BeforeEach void beforeEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeEach"); } @Test void test(String wisdom) { assertWisdom(crystalBall, wisdom, "@Test"); } @AfterEach void afterEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterEach"); } } @ExtendWith(ExtensionInjector.class) static class InstanceLevelExtensionRegistrationWithInjectedExtensionTestCase { @RegisterExtension protected CrystalBall crystalBall; // Injected by ExtensionInjector. @BeforeEach void beforeEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeEach"); } @Test void test(String wisdom) { assertWisdom(crystalBall, wisdom, "@Test"); } @AfterEach void afterEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterEach"); } } @TestInstance(PER_CLASS) static class InstanceLevelExtensionRegistrationWithTestInstancePerClassLifecycleTestCase { @RegisterExtension final CrystalBall crystalBall = new CrystalBall("Outlook good"); @BeforeAll void beforeAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeAll"); } @BeforeEach void beforeEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeEach"); } @Test void test(String wisdom) { assertWisdom(crystalBall, wisdom, "@Test"); } @AfterEach void afterEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterEach"); } @AfterAll void afterAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterAll"); } } static class ClassLevelExtensionRegistrationTestCase { @RegisterExtension static final CrystalBall crystalBall = new CrystalBall("Outlook good"); @BeforeAll static void beforeAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeAll"); } @BeforeEach void beforeEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeEach"); } @Test void test(String wisdom) { assertWisdom(crystalBall, wisdom, "@Test"); } @AfterEach void afterEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterEach"); } @AfterAll static void afterAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterAll"); } } static class SubClassLevelExtensionRegistrationTestCase extends ClassLevelExtensionRegistrationTestCase { @Test @Override void test(String wisdom) { assertWisdom(crystalBall, wisdom, "Overridden @Test"); } } interface ClassLevelExtensionRegistrationInterface { @RegisterExtension static CrystalBall crystalBall = new CrystalBall("Outlook good"); @BeforeAll static void beforeAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeAll"); } @BeforeEach default void beforeEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@BeforeEach"); } @AfterEach default void afterEach(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterEach"); } @AfterAll static void afterAll(String wisdom) { assertWisdom(crystalBall, wisdom, "@AfterAll"); } } static class ExtensionRegistrationFromInterfaceTestCase implements ClassLevelExtensionRegistrationInterface { @Test void test(String wisdom) { assertWisdom(crystalBall, wisdom, "@Test"); } } private static class CrystalBall implements ParameterResolver { private final String wisdom; public CrystalBall(String wisdom) { this.wisdom = wisdom; } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == String.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return this.wisdom; } } static class ClassLevelExtensionRegistrationParentTestCase { @RegisterExtension static BeforeEachCallback extension1 = context -> callSequence.add( ClassLevelExtensionRegistrationParentTestCase.class.getSimpleName() + " :: extension1: before " + context.getRequiredTestMethod().getName()); @RegisterExtension static BeforeEachCallback extension2 = context -> callSequence.add( ClassLevelExtensionRegistrationParentTestCase.class.getSimpleName() + " :: extension2: before " + context.getRequiredTestMethod().getName()); @Test void test() { } } static class ClassLevelExtensionRegistrationChildTestCase extends ClassLevelExtensionRegistrationParentTestCase { // "Hides" ClassLevelExtensionRegistrationParentTestCase.extension2 @RegisterExtension static BeforeEachCallback extension2 = context -> callSequence.add( ClassLevelExtensionRegistrationChildTestCase.class.getSimpleName() + " :: extension2: before " + context.getRequiredTestMethod().getName()); @RegisterExtension static BeforeEachCallback extension3 = context -> callSequence.add( ClassLevelExtensionRegistrationChildTestCase.class.getSimpleName() + " :: extension3: before " + context.getRequiredTestMethod().getName()); } static class InstanceLevelExtensionRegistrationParentTestCase { @RegisterExtension BeforeEachCallback extension1 = context -> callSequence.add( InstanceLevelExtensionRegistrationParentTestCase.class.getSimpleName() + " :: extension1: before " + context.getRequiredTestMethod().getName()); @RegisterExtension BeforeEachCallback extension2 = context -> callSequence.add( InstanceLevelExtensionRegistrationParentTestCase.class.getSimpleName() + " :: extension2: before " + context.getRequiredTestMethod().getName()); @Test void test() { } } static class InstanceLevelExtensionRegistrationChildTestCase extends InstanceLevelExtensionRegistrationParentTestCase { // "Hides" InstanceLevelExtensionRegistrationParentTestCase.extension2 @RegisterExtension BeforeEachCallback extension2 = context -> callSequence.add( InstanceLevelExtensionRegistrationChildTestCase.class.getSimpleName() + " :: extension2: before " + context.getRequiredTestMethod().getName()); @RegisterExtension BeforeEachCallback extension3 = context -> callSequence.add( InstanceLevelExtensionRegistrationChildTestCase.class.getSimpleName() + " :: extension3: before " + context.getRequiredTestMethod().getName()); } /** * This interface intentionally does not implement a supported {@link Extension} API. */ interface CustomExtension { void doSomething(); } static class CustomExtensionImpl implements CustomExtension, BeforeEachCallback { @Override public void doSomething() { callSequence.add(getClass().getSimpleName() + " :: doSomething()"); } @Override public void beforeEach(ExtensionContext context) throws Exception { callSequence.add(getClass().getSimpleName() + " :: before " + context.getRequiredTestMethod().getName()); } } static class InstanceLevelCustomExtensionApiTestCase { @RegisterExtension CustomExtension extension = new CustomExtensionImpl(); @Test void test() { this.extension.doSomething(); } } static class ClassLevelCustomExtensionApiTestCase { @RegisterExtension static CustomExtension extension = new CustomExtensionImpl(); @Test void test() { extension.doSomething(); } } static class AbstractTestCase { @Test void test() { } } static class InstanceLevelExtensionRegistrationWithPrivateFieldTestCase extends AbstractTestCase { @RegisterExtension private Extension extension = new Extension() { }; } static class ClassLevelExtensionRegistrationWithPrivateFieldTestCase extends AbstractTestCase { @RegisterExtension private static Extension extension = new Extension() { }; } static class InstanceLevelExtensionRegistrationWithNullFieldTestCase extends AbstractTestCase { @RegisterExtension Extension extension; } static class ClassLevelExtensionRegistrationWithNullFieldTestCase extends AbstractTestCase { @RegisterExtension static Extension extension; } static class InstanceLevelExtensionRegistrationWithNonExtensionFieldValueTestCase extends AbstractTestCase { @RegisterExtension Object extension = "not an extension type"; } static class ClassLevelExtensionRegistrationWithNonExtensionFieldValueTestCase extends AbstractTestCase { @RegisterExtension static Object extension = "not an extension type"; } static class ClassLevelExplosiveCheckedExceptionTestCase extends AbstractTestCase { @RegisterExtension static Extension field = new ExplosiveExtension(new Exception("boom")); } static class ClassLevelExplosiveUncheckedExceptionTestCase extends AbstractTestCase { @RegisterExtension static Extension field = new ExplosiveExtension(new RuntimeException("boom")); } static class ClassLevelExplosiveErrorTestCase extends AbstractTestCase { @RegisterExtension static Extension field = new ExplosiveExtension(new Error("boom")); } static class InstanceLevelExplosiveCheckedExceptionTestCase extends AbstractTestCase { @RegisterExtension Extension field = new ExplosiveExtension(new Exception("boom")); } static class InstanceLevelExplosiveUncheckedExceptionTestCase extends AbstractTestCase { @RegisterExtension Extension field = new ExplosiveExtension(new RuntimeException("boom")); } static class InstanceLevelExplosiveErrorTestCase extends AbstractTestCase { @RegisterExtension Extension field = new ExplosiveExtension(new Error("boom")); } static class ExplosiveExtension implements Extension { ExplosiveExtension(Throwable t) { throw ExceptionUtils.throwAsUncheckedException(t); } } /** * Mimics a dependency injection framework such as Spring, Guice, CDI, etc., * where the instance of the extension registered via * {@link RegisterExtension @RegisterExtension} is managed by the DI * framework and injected into the test instance. */ private static class ExtensionInjector implements TestInstancePostProcessor { private static final Predicate isCrystalBall = field -> CrystalBall.class.isAssignableFrom( field.getType()); @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { // @formatter:off AnnotationUtils.findAnnotatedFields(testInstance.getClass(), RegisterExtension.class, isCrystalBall).stream() .findFirst() .ifPresent(field -> { try { ReflectionUtils.makeAccessible(field); field.set(testInstance, new CrystalBall("Outlook good")); } catch (Throwable t) { ExceptionUtils.throwAsUncheckedException(t); } }); // @formatter:on } } static class TwoNestedClassesTestCase { @RegisterExtension Extension extension = new LongParameterResolver(); @Nested class A { @Test void first(Long n) { assertEquals(42L, n); } @Test void second(Long n) { assertEquals(42L, n); } } @Nested class B { @Test void first(Long n) { assertEquals(42L, n); } @Test void second(Long n) { assertEquals(42L, n); } } } } RandomlyOrderedTests.java000066400000000000000000000054351455764576500355650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.IntStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; /** * @since 5.8 */ class RandomlyOrderedTests { private static final Set callSequence = Collections.synchronizedSet(new LinkedHashSet<>()); @Test void randomSeedForClassAndMethodOrderingIsDeterministic() { IntStream.range(0, 20).forEach(i -> { callSequence.clear(); var tests = executeTests(1618034L); tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence).containsExactlyInAnyOrder("B_TestCase#b", "B_TestCase#c", "B_TestCase#a", "C_TestCase#b", "C_TestCase#c", "C_TestCase#a", "A_TestCase#b", "A_TestCase#c", "A_TestCase#a"); }); } private Events executeTests(long randomSeed) { // @formatter:off return EngineTestKit .engine("junit-jupiter") .configurationParameter(DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME, ClassOrderer.Random.class.getName()) .configurationParameter(DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME, MethodOrderer.Random.class.getName()) .configurationParameter(MethodOrderer.Random.RANDOM_SEED_PROPERTY_NAME, String.valueOf(randomSeed)) .selectors(selectClass(A_TestCase.class), selectClass(B_TestCase.class), selectClass(C_TestCase.class)) .execute() .testEvents(); // @formatter:on } abstract static class BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { var testClass = testInfo.getTestClass().get(); var testMethod = testInfo.getTestMethod().get(); callSequence.add(testClass.getSimpleName() + "#" + testMethod.getName()); } @Test void a() { } @Test void b() { } @Test void c() { } } static class A_TestCase extends BaseTestCase { } static class B_TestCase extends BaseTestCase { } static class C_TestCase extends BaseTestCase { } } RepeatedTestTests.java000066400000000000000000000355271455764576500350710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.engine.Constants.DEFAULT_PARALLEL_EXECUTION_MODE; import static org.junit.jupiter.engine.Constants.PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicInteger; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.Events; /** * Integration tests for {@link RepeatedTest @RepeatedTest} and supporting * infrastructure. * * @since 5.0 */ class RepeatedTestTests extends AbstractJupiterTestEngineTests { @RepeatedTest(1) @DisplayName("Repeat!") void customDisplayName(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("repetition 1 of 1"); } @RepeatedTest(1) @DisplayName(" \t ") void customDisplayNameWithBlankName(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("repetition 1 of 1"); } @RepeatedTest(value = 1, name = "{displayName}") @DisplayName("Repeat!") void customDisplayNameWithPatternIncludingDisplayName(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("Repeat!"); } @RepeatedTest(value = 1, name = "#{currentRepetition}") @DisplayName("Repeat!") void customDisplayNameWithPatternIncludingCurrentRepetition(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("#1"); } @RepeatedTest(value = 1, name = "Repetition #{currentRepetition} for {displayName}") @DisplayName("Repeat!") void customDisplayNameWithPatternIncludingDisplayNameAndCurrentRepetition(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("Repetition #1 for Repeat!"); } @RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME) @DisplayName("Repeat!") void customDisplayNameWithPredefinedLongPattern(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("Repeat! :: repetition 1 of 1"); } @RepeatedTest(value = 1, name = "{displayName} {currentRepetition}/{totalRepetitions}") @DisplayName("Repeat!") void customDisplayNameWithPatternIncludingDisplayNameCurrentRepetitionAndTotalRepetitions(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("Repeat! 1/1"); } @RepeatedTest(value = 1, name = "Repetition #{currentRepetition} for {displayName}") void defaultDisplayNameWithPatternIncludingDisplayNameAndCurrentRepetition(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo( "Repetition #1 for defaultDisplayNameWithPatternIncludingDisplayNameAndCurrentRepetition(TestInfo)"); } @RepeatedTest(value = 5, name = "{displayName}") void injectRepetitionInfo(TestInfo testInfo, RepetitionInfo repetitionInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("injectRepetitionInfo(TestInfo, RepetitionInfo)"); assertThat(repetitionInfo.getCurrentRepetition()).isBetween(1, 5); assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(5); } @Nested class LifecycleMethodTests { private static int fortyTwo = 0; @AfterAll static void afterAll() { assertEquals(42, fortyTwo); } @BeforeEach @AfterEach void beforeAndAfterEach(TestInfo testInfo, RepetitionInfo repetitionInfo) { switch (testInfo.getTestMethod().get().getName()) { case "repeatedOnce": { assertThat(repetitionInfo.getCurrentRepetition()).isEqualTo(1); assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(1); break; } case "repeatedFortyTwoTimes": { assertThat(repetitionInfo.getCurrentRepetition()).isBetween(1, 42); assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(42); break; } } } @RepeatedTest(1) void repeatedOnce(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).isEqualTo("repetition 1 of 1"); } @RepeatedTest(42) void repeatedFortyTwoTimes(TestInfo testInfo) { assertThat(testInfo.getDisplayName()).matches("repetition \\d+ of 42"); fortyTwo++; } } @Nested class FailureTests { private static final Condition emptyPattern = message( value -> value.contains("must be declared with a non-empty name")); private static final Condition invalidRepetitionCount = message( value -> value.contains("must be declared with a positive 'value'")); private static final Condition invalidThreshold = message(value -> value.endsWith( "must declare a 'failureThreshold' greater than zero and less than the total number of repetitions [10].")); @BeforeEach void resetCounter() { TestCase.counter.set(0); } @Test void failsContainerForEmptyPattern() { executeTest("testWithEmptyPattern").assertThatEvents() // .haveExactly(1, event(container(), displayName("testWithEmptyPattern()"), // finishedWithFailure(emptyPattern))); } @Test void failsContainerForBlankPattern() { executeTest("testWithBlankPattern").assertThatEvents() // .haveExactly(1, event(container(), displayName("testWithBlankPattern()"), // finishedWithFailure(emptyPattern))); } @Test void failsContainerForNegativeRepeatCount() { executeTest("negativeRepeatCount").assertThatEvents() // .haveExactly(1, event(container(), displayName("negativeRepeatCount()"), // finishedWithFailure(invalidRepetitionCount))); } @Test void failsContainerForZeroRepeatCount() { executeTest("zeroRepeatCount").assertThatEvents() // .haveExactly(1, event(container(), displayName("zeroRepeatCount()"), // finishedWithFailure(invalidRepetitionCount))); } @Test void failsContainerForFailureThresholdSetToNegativeValue() { executeTest("failureThresholdSetToNegativeValue").assertThatEvents() // .haveExactly(1, event(container(), displayName("failureThresholdSetToNegativeValue()"), // finishedWithFailure(invalidThreshold))); } @Test void failsContainerForFailureThresholdSetToZero() { executeTest("failureThresholdSetToZero").assertThatEvents() // .haveExactly(1, event(container(), displayName("failureThresholdSetToZero()"), // finishedWithFailure(invalidThreshold))); } @Test void failsContainerForFailureThresholdGreaterThanRepetitionCount() { executeTest("failureThresholdGreaterThanRepetitionCount").assertThatEvents() // .haveExactly(1, event(container(), displayName("failureThresholdGreaterThanRepetitionCount()"), // finishedWithFailure(invalidThreshold))); } @Test void failsContainerForFailureThresholdEqualToRepetitionCount() { executeTest("failureThresholdEqualToRepetitionCount").assertThatEvents() // .haveExactly(1, event(container(), displayName("failureThresholdEqualToRepetitionCount()"), // finishedWithFailure(invalidThreshold))); } @Test void failureThresholdEqualToRepetitionCountMinusOne() { String methodName = "failureThresholdEqualToRepetitionCountMinusOne"; // @formatter:off executeTest(methodName).assertEventsMatchLooselyInOrder( event(container(methodName), started()), event(test("test-template-invocation:#1"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#2"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#3"), skippedWithReason("Failure threshold [2] exceeded")), event(container(methodName), finishedSuccessfully())); // @formatter:on } @Test void failureThreshold1() { String methodName = "failureThreshold1"; // @formatter:off executeTest(methodName).assertEventsMatchLooselyInOrder( event(container(methodName), started()), event(test("test-template-invocation:#1"), finishedSuccessfully()), event(test("test-template-invocation:#2"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#3"), skippedWithReason("Failure threshold [1] exceeded")), event(container(methodName), finishedSuccessfully())); // @formatter:on } @Test void failureThreshold2() { String methodName = "failureThreshold2"; // @formatter:off executeTest(methodName).assertEventsMatchLooselyInOrder( event(container(methodName), started()), event(test("test-template-invocation:#1"), finishedSuccessfully()), event(test("test-template-invocation:#2"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#3"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#4"), skippedWithReason("Failure threshold [2] exceeded")), event(container(methodName), finishedSuccessfully())); // @formatter:on } @Test void failureThreshold3() { String methodName = "failureThreshold3"; // @formatter:off executeTest(methodName).assertEventsMatchLooselyInOrder( event(container(methodName), started()), event(test("test-template-invocation:#1"), finishedSuccessfully()), event(test("test-template-invocation:#2"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#3"), finishedSuccessfully()), event(test("test-template-invocation:#4"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#5"), finishedSuccessfully()), event(test("test-template-invocation:#6"), finishedWithFailure(message("Boom!"))), event(test("test-template-invocation:#7"), skippedWithReason("Failure threshold [3] exceeded")), event(test("test-template-invocation:#8"), skippedWithReason("Failure threshold [3] exceeded")), event(container(methodName), finishedSuccessfully())); // @formatter:on } @Test void failureThresholdWithConcurrentExecution() { Class testClass = TestCase.class; String methodName = "failureThresholdWithConcurrentExecution"; Method method = ReflectionUtils.findMethod(testClass, methodName).get(); LauncherDiscoveryRequest request = request()// .selectors(selectMethod(testClass, method))// .configurationParameter(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true")// .configurationParameter(DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent")// .configurationParameter(PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME, "fixed")// .configurationParameter(PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, "4")// .build(); Events tests = executeTests(request).testEvents(); // There are 20 repetitions/tests in total. assertThat(tests.dynamicallyRegistered().count()).as("registered").isEqualTo(20); assertThat(tests.started().count() + tests.skipped().count()).as("started or skipped").isEqualTo(20); // Would be 3 successful tests without parallel execution, but with race conditions // and multiple threads we may encounter more; and yet we still should not // encounter too many. assertThat(tests.succeeded().count()).as("succeeded").isBetween(3L, 10L); // Would be 3 failed tests without parallel execution, but with race conditions // and multiple threads we may encounter more. assertThat(tests.failed().count()).as("failed").isGreaterThanOrEqualTo(3); // Would be 14 skipped tests without parallel execution, but with race conditions // and multiple threads we may not encounter many. assertThat(tests.skipped().count()).as("skipped").isGreaterThan(0); } private Events executeTest(String methodName) { Class testClass = TestCase.class; Method method = ReflectionUtils.findMethod(testClass, methodName).get(); return executeTests(selectMethod(testClass, method)).allEvents(); } } static class TestCase { static final AtomicInteger counter = new AtomicInteger(); @RepeatedTest(value = 1, name = "") void testWithEmptyPattern() { } @RepeatedTest(value = 1, name = " \t ") void testWithBlankPattern() { } @RepeatedTest(-99) void negativeRepeatCount() { } @RepeatedTest(0) void zeroRepeatCount() { } @RepeatedTest(value = 10, failureThreshold = -1) void failureThresholdSetToNegativeValue() { fail("Boom!"); } @RepeatedTest(value = 10, failureThreshold = 0) void failureThresholdSetToZero() { fail("Boom!"); } @RepeatedTest(value = 10, failureThreshold = 11) void failureThresholdGreaterThanRepetitionCount() { fail("Boom!"); } @RepeatedTest(value = 10, failureThreshold = 10) void failureThresholdEqualToRepetitionCount() { fail("Boom!"); } @RepeatedTest(value = 3, failureThreshold = 2) void failureThresholdEqualToRepetitionCountMinusOne() { fail("Boom!"); } @RepeatedTest(value = 3, failureThreshold = 1) void failureThreshold1() { int count = counter.incrementAndGet(); if (count > 1) { fail("Boom!"); } } @RepeatedTest(value = 4, failureThreshold = 2) void failureThreshold2() { int count = counter.incrementAndGet(); if (count > 1) { fail("Boom!"); } } @RepeatedTest(value = 8, failureThreshold = 3) void failureThreshold3() { int count = counter.incrementAndGet(); if ((count > 1) && (count % 2 == 0)) { fail("Boom!"); } } @RepeatedTest(value = 20, failureThreshold = 3) void failureThresholdWithConcurrentExecution() { int count = counter.incrementAndGet(); if ((count > 1) && (count % 2 == 0)) { fail("Boom!"); } } } } SameThreadTimeoutInvocationTests.java000066400000000000000000000034771455764576500401150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.ThrowingConsumer; /** * @since 5.5 */ class SameThreadTimeoutInvocationTests { @Test void resetsInterruptFlag() { var exception = assertThrows(TimeoutException.class, () -> withExecutor(executor -> { var delegate = new EventuallyInterruptibleInvocation(); var duration = new TimeoutDuration(1, NANOSECONDS); var timeoutInvocation = new SameThreadTimeoutInvocation<>(delegate, duration, executor, () -> "execution"); timeoutInvocation.proceed(); })); assertFalse(Thread.currentThread().isInterrupted()); assertThat(exception).hasMessage("execution timed out after 1 nanosecond"); } private void withExecutor(ThrowingConsumer consumer) throws Throwable { ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); try { consumer.accept(executor); } finally { executor.shutdown(); assertTrue(executor.awaitTermination(5, SECONDS)); } } } SeparateThreadTimeoutInvocationTests.java000066400000000000000000000062501455764576500407640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.condition.OS.WINDOWS; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.engine.execution.NamespaceAwareStore; import org.junit.jupiter.engine.extension.TimeoutInvocationFactory.TimeoutInvocationParameters; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; /** * @since 5.9 */ @DisplayName("SeparateThreadTimeoutInvocation") class SeparateThreadTimeoutInvocationTests { private static final long PREEMPTIVE_TIMEOUT_MILLIS = WINDOWS.isCurrentOs() ? 1000 : 100; @Test @DisplayName("throws timeout exception when timeout duration is exceeded") void throwsTimeoutException() { AtomicReference threadName = new AtomicReference<>(); var invocation = aSeparateThreadInvocation(() -> { threadName.set(Thread.currentThread().getName()); Thread.sleep(PREEMPTIVE_TIMEOUT_MILLIS * 2); return null; }); assertThatThrownBy(invocation::proceed) // .hasMessage("method() timed out after " + PREEMPTIVE_TIMEOUT_MILLIS + " milliseconds") // .isInstanceOf(TimeoutException.class) // .hasRootCauseMessage("Execution timed out in thread " + threadName.get()); } @Test @DisplayName("executes invocation in a separate thread") void runsInvocationUsingSeparateThread() throws Throwable { var invocationThreadName = aSeparateThreadInvocation(() -> Thread.currentThread().getName()).proceed(); assertThat(invocationThreadName).isNotEqualTo(Thread.currentThread().getName()); } @Test @DisplayName("throws invocation exception") void shouldThrowInvocationException() { var invocation = aSeparateThreadInvocation(() -> { throw new RuntimeException("hi!"); }); assertThatThrownBy(invocation::proceed) // .isInstanceOf(RuntimeException.class) // .hasMessage("hi!"); } private static SeparateThreadTimeoutInvocation aSeparateThreadInvocation(Invocation invocation) { var namespace = ExtensionContext.Namespace.create(SeparateThreadTimeoutInvocationTests.class); var store = new NamespaceAwareStore(new NamespacedHierarchicalStore<>(null), namespace); var parameters = new TimeoutInvocationParameters<>(invocation, new TimeoutDuration(PREEMPTIVE_TIMEOUT_MILLIS, MILLISECONDS), () -> "method()"); return (SeparateThreadTimeoutInvocation) new TimeoutInvocationFactory(store) // .create(ThreadMode.SEPARATE_THREAD, parameters); } } ServiceLoaderExtension.java000066400000000000000000000013601455764576500360650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; /** * Demo extension for auto-detection of extensions loaded via Java's * {@link java.util.ServiceLoader} mechanism. * * @since 5.0 */ public class ServiceLoaderExtension implements BeforeAllCallback { @Override public void beforeAll(ExtensionContext context) { } } TempDirectoryCleanupTests.java000066400000000000000000000302461455764576500365730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.nio.file.Files.deleteIfExists; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.api.io.CleanupMode.NEVER; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.io.IOException; import java.nio.file.Path; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * Test that {@linkplain TempDir temporary directories} are not deleted with * {@link CleanupMode#NEVER}, are deleted with {@link CleanupMode#ON_SUCCESS} * but only if the test passes, and are always deleted with {@link CleanupMode#ALWAYS}. * * @see CleanupMode * @see TempDir * @since 5.9 */ class TempDirectoryCleanupTests extends AbstractJupiterTestEngineTests { @Nested class TempDirFieldTests { private static Path defaultFieldDir; private static Path neverFieldDir; private static Path alwaysFieldDir; private static Path onSuccessFailingFieldDir; private static Path onSuccessPassingFieldDir; /** * Ensure the cleanup mode defaults to ALWAYS for fields. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeDefaultField() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(DefaultFieldCase.class, "testDefaultField"))// .build(); executeTests(request); assertThat(defaultFieldDir).doesNotExist(); } /** * Ensure that a custom, global cleanup mode is used for fields. *

* Expect the TempDir NOT to be cleaned up if set to NEVER. */ @Test void cleanupModeCustomDefaultField() { LauncherDiscoveryRequest request = request()// .configurationParameter(TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME, "never")// .selectors(selectMethod(DefaultFieldCase.class, "testDefaultField"))// .build(); executeTests(request); assertThat(defaultFieldDir).exists(); } /** * Ensure that NEVER cleanup modes are obeyed for fields. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeNeverField() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(NeverFieldCase.class, "testNeverField"))// .build(); executeTests(request); assertThat(neverFieldDir).exists(); } /** * Ensure that ALWAYS cleanup modes are obeyed for fields. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeAlwaysField() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(AlwaysFieldCase.class, "testAlwaysField"))// .build(); executeTests(request); assertThat(alwaysFieldDir).doesNotExist(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for passing field tests. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeOnSuccessPassingField() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(OnSuccessPassingFieldCase.class, "testOnSuccessPassingField"))// .build(); executeTests(request); assertThat(onSuccessPassingFieldDir).doesNotExist(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for failing field tests. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeOnSuccessFailingField() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(OnSuccessFailingFieldCase.class, "testOnSuccessFailingField"))// .build(); executeTests(request); assertThat(onSuccessFailingFieldDir).exists(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for static fields when tests are failing. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeOnSuccessFailingStaticField() { LauncherDiscoveryRequest request = request()// .selectors(selectClass(OnSuccessFailingStaticFieldCase.class))// .build(); executeTests(request); assertThat(onSuccessFailingFieldDir).exists(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for static fields when nested tests are failing. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeOnSuccessFailingStaticFieldWithNesting() { LauncherDiscoveryRequest request = request()// .selectors(selectClass(OnSuccessFailingStaticFieldWithNestingCase.class))// .build(); executeTests(request); assertThat(onSuccessFailingFieldDir).exists(); } @AfterAll static void afterAll() throws IOException { deleteIfNotNullAndExists(defaultFieldDir); deleteIfNotNullAndExists(neverFieldDir); deleteIfNotNullAndExists(alwaysFieldDir); deleteIfNotNullAndExists(onSuccessFailingFieldDir); deleteIfNotNullAndExists(onSuccessPassingFieldDir); } static void deleteIfNotNullAndExists(Path dir) throws IOException { if (dir != null) { deleteIfExists(dir); } } // ------------------------------------------------------------------- static class DefaultFieldCase { @TempDir Path defaultFieldDir; @Test void testDefaultField() { TempDirFieldTests.defaultFieldDir = defaultFieldDir; } } static class NeverFieldCase { @TempDir(cleanup = NEVER) Path neverFieldDir; @Test void testNeverField() { TempDirFieldTests.neverFieldDir = neverFieldDir; } } static class AlwaysFieldCase { @TempDir(cleanup = ALWAYS) Path alwaysFieldDir; @Test void testAlwaysField() { TempDirFieldTests.alwaysFieldDir = alwaysFieldDir; } } static class OnSuccessPassingFieldCase { @TempDir(cleanup = ON_SUCCESS) Path onSuccessPassingFieldDir; @Test void testOnSuccessPassingField() { TempDirFieldTests.onSuccessPassingFieldDir = onSuccessPassingFieldDir; } } static class OnSuccessFailingFieldCase { @TempDir(cleanup = ON_SUCCESS) Path onSuccessFailingFieldDir; @Test void testOnSuccessFailingField() { TempDirFieldTests.onSuccessFailingFieldDir = onSuccessFailingFieldDir; fail(); } } @TestMethodOrder(MethodOrderer.OrderAnnotation.class) static class OnSuccessFailingStaticFieldCase { @TempDir(cleanup = ON_SUCCESS) static Path onSuccessFailingFieldDir; @Test @Order(1) void failing() { TempDirFieldTests.onSuccessFailingFieldDir = onSuccessFailingFieldDir; fail(); } @Test @Order(2) void passing() { } } static class OnSuccessFailingStaticFieldWithNestingCase { @TempDir(cleanup = ON_SUCCESS) static Path onSuccessFailingFieldDir; @Nested class NestedTestCase { @Test void test() { TempDirFieldTests.onSuccessFailingFieldDir = onSuccessFailingFieldDir; fail(); } } } } @Nested class TempDirParameterTests { private static Path defaultParameterDir; private static Path neverParameterDir; private static Path alwaysParameterDir; private static Path onSuccessFailingParameterDir; private static Path onSuccessPassingParameterDir; /** * Ensure the cleanup mode defaults to ALWAYS for parameters. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeDefaultParameter() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(DefaultParameterCase.class, "testDefaultParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(defaultParameterDir).doesNotExist(); } /** * Ensure that a custom, global cleanup mode is used for parameters. *

* Expect the TempDir NOT to be cleaned up if set to NEVER. */ @Test void cleanupModeCustomDefaultParameter() { LauncherDiscoveryRequest request = request()// .configurationParameter(TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME, "never")// .selectors(selectMethod(DefaultParameterCase.class, "testDefaultParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(defaultParameterDir).exists(); } /** * Ensure that NEVER cleanup modes are obeyed for parameters. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeNeverParameter() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(NeverParameterCase.class, "testNeverParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(neverParameterDir).exists(); } /** * Ensure that ALWAYS cleanup modes are obeyed for parameters. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeAlwaysParameter() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(AlwaysParameterCase.class, "testAlwaysParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(alwaysParameterDir).doesNotExist(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for passing parameter tests. *

* Expect the TempDir to be cleaned up. */ @Test void cleanupModeOnSuccessPassingParameter() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(OnSuccessPassingParameterCase.class, "testOnSuccessPassingParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(onSuccessPassingParameterDir).doesNotExist(); } /** * Ensure that ON_SUCCESS cleanup modes are obeyed for failing parameter tests. *

* Expect the TempDir not to be cleaned up. */ @Test void cleanupModeOnSuccessFailingParameter() { LauncherDiscoveryRequest request = request()// .selectors(selectMethod(OnSuccessFailingParameterCase.class, "testOnSuccessFailingParameter", "java.nio.file.Path"))// .build(); executeTests(request); assertThat(onSuccessFailingParameterDir).exists(); } @AfterAll static void afterAll() throws IOException { TempDirFieldTests.deleteIfNotNullAndExists(defaultParameterDir); TempDirFieldTests.deleteIfNotNullAndExists(neverParameterDir); TempDirFieldTests.deleteIfNotNullAndExists(alwaysParameterDir); TempDirFieldTests.deleteIfNotNullAndExists(onSuccessFailingParameterDir); TempDirFieldTests.deleteIfNotNullAndExists(onSuccessPassingParameterDir); } // ------------------------------------------------------------------- static class DefaultParameterCase { @Test void testDefaultParameter(@TempDir Path defaultParameterDir) { TempDirParameterTests.defaultParameterDir = defaultParameterDir; } } static class NeverParameterCase { @Test void testNeverParameter(@TempDir(cleanup = NEVER) Path neverParameterDir) { TempDirParameterTests.neverParameterDir = neverParameterDir; } } static class AlwaysParameterCase { @Test void testAlwaysParameter(@TempDir(cleanup = ALWAYS) Path alwaysParameterDir) { TempDirParameterTests.alwaysParameterDir = alwaysParameterDir; } } static class OnSuccessPassingParameterCase { @Test void testOnSuccessPassingParameter(@TempDir(cleanup = ON_SUCCESS) Path onSuccessPassingParameterDir) { TempDirParameterTests.onSuccessPassingParameterDir = onSuccessPassingParameterDir; } } static class OnSuccessFailingParameterCase { @Test void testOnSuccessFailingParameter(@TempDir(cleanup = ON_SUCCESS) Path onSuccessFailingParameterDir) { TempDirParameterTests.onSuccessFailingParameterDir = onSuccessFailingParameterDir; fail(); } } } } TempDirectoryMetaAnnotationTests.java000066400000000000000000000034561455764576500401300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; /** * Integration tests for the use of {@link TempDir} as a meta-annotation. * * @since 5.10 */ @DisplayName("@TempDir as a meta-annotation") class TempDirectoryMetaAnnotationTests extends AbstractJupiterTestEngineTests { @Test void annotationOnField() { executeTestsForClass(AnnotationOnFieldTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test void annotationOnParameter() { executeTestsForClass(AnnotationOnParameterTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } static class AnnotationOnFieldTestCase { @CustomTempDir private Path tempDir; @Test void test() { assertTrue(Files.exists(tempDir)); } } static class AnnotationOnParameterTestCase { @Test void test(@CustomTempDir Path tempDir) { assertTrue(Files.exists(tempDir)); } } @TempDir @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @interface CustomTempDir { } } TempDirectoryPerContextTests.java000066400000000000000000001351061455764576500373000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.cause; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.DosFileAttributeView; import java.util.Deque; import java.util.LinkedList; import java.util.function.Supplier; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests for the legacy behavior of the {@link TempDirectory} * extension to create a single temp directory per context, i.e. test class or * method. * * @since 5.4 */ @DisplayName("TempDirectory extension (per context)") class TempDirectoryPerContextTests extends AbstractJupiterTestEngineTests { @Override protected EngineExecutionResults executeTestsForClass(Class testClass) { return executeTests(requestBuilder(testClass).build()); } @SuppressWarnings("deprecation") private static LauncherDiscoveryRequestBuilder requestBuilder(Class testClass) { return request() // .selectors(selectClass(testClass)) // .configurationParameter(TempDir.SCOPE_PROPERTY_NAME, TempDirectory.Scope.PER_CONTEXT.name()); } @BeforeEach @AfterEach void resetStaticVariables() { BaseSharedTempDirFieldInjectionTestCase.staticTempDir = null; BaseSharedTempDirParameterInjectionTestCase.tempDir = null; BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.clear(); BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.clear(); } @Test @DisplayName("does not prevent constructor parameter resolution") void tempDirectoryDoesNotPreventConstructorParameterResolution() { executeTestsForClass(TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("does not prevent user from deleting the temp dir within a test") void tempDirectoryDoesNotPreventUserFromDeletingTempDir() { executeTestsForClass(UserTempDirectoryDeletionDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("is capable of removing a read-only file") void nonWritableFileDoesNotCauseFailure() { executeTestsForClass(NonWritableFileDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("is capable of removing non-executable, non-writable, or non-readable directories and folders") void nonMintPermissionsContentDoesNotCauseFailure() { executeTestsForClass(NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(13).succeeded(13)); } @Test @DisplayName("is capable of removing a directory when its permissions have been changed") void nonMintPermissionsDoNotCauseFailure() { executeTestsForClass(NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(42).succeeded(42)); } @Test @DisplayName("is capable of removing a read-only file in a read-only dir") void readOnlyFileInReadOnlyDirDoesNotCauseFailure() { executeTestsForClass(ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("is capable of removing a read-only file in a dir in a read-only dir") void readOnlyFileInNestedReadOnlyDirDoesNotCauseFailure() { executeTestsForClass(ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("can be used via instance field inside nested test classes") void canBeUsedViaInstanceFieldInsideNestedTestClasses() { executeTestsForClass(TempDirUsageInsideNestedClassesTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(3).succeeded(3)); } @Test @DisplayName("can be used via static field inside nested test classes") void canBeUsedViaStaticFieldInsideNestedTestClasses() { executeTestsForClass(StaticTempDirUsageInsideNestedClassTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); } @Test @DisplayName("resolves java.io.File injection type") void resolvesFileInstances() { executeTestsForClass(FileInjectionTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Nested @DisplayName("resolves shared temp dir") @TestMethodOrder(OrderAnnotation.class) class SharedTempDir { @Test @DisplayName("when @TempDir is used on static field") @Order(10) void resolvesSharedTempDirWhenAnnotationIsUsedOnStaticField() { assertSharedTempDirForFieldInjection(AnnotationOnStaticFieldTestCase.class); } @Test @DisplayName("when @TempDir is used on static field and @BeforeAll method parameter") @Order(11) void resolvesSharedTempDirWhenAnnotationIsUsedOnStaticFieldAndBeforeAllMethodParameter() { assertSharedTempDirForFieldInjection(AnnotationOnStaticFieldAndBeforeAllMethodParameterTestCase.class); } @Test @DisplayName("when @TempDir is used on instance field and @BeforeAll method parameter") @Order(14) void resolvesSharedTempDirWhenAnnotationIsUsedOnInstanceFieldAndBeforeAllMethodParameter() { assertSharedTempDirForFieldInjection(AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase.class); } @Test @DisplayName("when @TempDir is used on instance field and @BeforeAll method parameter with @TestInstance(PER_CLASS)") @Order(15) void resolvesSharedTempDirWhenAnnotationIsUsedOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClass() { assertSharedTempDirForFieldInjection( AnnotationOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClassTestCase.class); } @Test @DisplayName("when @TempDir is used on @BeforeAll method parameter") @Order(23) void resolvesSharedTempDirWhenAnnotationIsUsedOnBeforeAllMethodParameter() { assertSharedTempDirForParameterInjection(AnnotationOnBeforeAllMethodParameterTestCase.class); } @Test @DisplayName("when @TempDir is used on @BeforeAll method parameter with @TestInstance(PER_CLASS)") @Order(24) void resolvesSharedTempDirWhenAnnotationIsUsedOnBeforeAllMethodParameterWithTestInstancePerClass() { assertSharedTempDirForParameterInjection( AnnotationOnBeforeAllMethodParameterWithTestInstancePerClassTestCase.class); } private void assertSharedTempDirForFieldInjection( Class testClass) { assertSharedTempDirForParameterInjection(testClass, () -> BaseSharedTempDirFieldInjectionTestCase.staticTempDir); } private void assertSharedTempDirForParameterInjection( Class testClass) { assertSharedTempDirForParameterInjection(testClass, () -> BaseSharedTempDirParameterInjectionTestCase.tempDir); } private void assertSharedTempDirForParameterInjection(Class testClass, Supplier staticTempDir) { var results = executeTestsForClass(testClass); results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); assertThat(staticTempDir.get()).isNotNull().doesNotExist(); } } @Nested @DisplayName("resolves separate temp dirs") @TestMethodOrder(OrderAnnotation.class) class SeparateTempDirs { @Test @DisplayName("when @TempDir is used on instance field") @Order(11) void resolvesSeparateTempDirWhenAnnotationIsUsedOnInstanceField() { assertSeparateTempDirsForFieldInjection( SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase.class); assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getFirst()).doesNotExist(); assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getLast()).doesNotExist(); } @Test @DisplayName("when @TempDir is used on instance field with @TestInstance(PER_CLASS)") @Order(12) void resolvesSeparateTempDirWhenAnnotationIsUsedOnInstanceFieldWithTestInstancePerClass() { assertSeparateTempDirsForFieldInjection( SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassFieldInjectionTestCase.class); assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getFirst()).doesNotExist(); assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getLast()).doesNotExist(); } @Test @DisplayName("when @TempDir is used on @BeforeEach/@AfterEach method parameters") @Order(21) void resolvesSeparateTempDirsWhenUsedOnForEachLifecycleMethods() { assertSeparateTempDirsForParameterInjection( SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase.class); assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getFirst()).doesNotExist(); assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getLast()).doesNotExist(); } @Test @DisplayName("when @TempDir is used on @BeforeEach/@AfterEach method parameters with @TestInstance(PER_CLASS)") @Order(22) void resolvesSeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClass() { assertSeparateTempDirsForParameterInjection( SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassParameterInjectionTestCase.class); assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getFirst()).doesNotExist(); assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getLast()).doesNotExist(); } @Test @DisplayName("for @AfterAll method parameter when @TempDir is not used on constructor or @BeforeAll method parameter") @Order(31) void resolvesSeparateTempDirWhenAnnotationIsUsedOnAfterAllMethodParameterOnly() { var results = executeTestsForClass(AnnotationOnAfterAllMethodParameterTestCase.class); results.testEvents().assertStatistics(stats -> stats.started(1).failed(0).succeeded(1)); assertThat(AnnotationOnAfterAllMethodParameterTestCase.firstTempDir).isNotNull().doesNotExist(); assertThat(AnnotationOnAfterAllMethodParameterTestCase.secondTempDir).isNotNull().doesNotExist(); } } @Nested @DisplayName("supports default factory") @TestMethodOrder(OrderAnnotation.class) class DefaultFactory { private Events executeTestsForClassWithDefaultFactory(Class testClass, Class factoryClass) { return TempDirectoryPerContextTests.super.executeTests(requestBuilder(testClass) // .configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) // .build()).testEvents(); } @Test @DisplayName("set to Jupiter's default") void supportsStandardDefaultFactory() { executeTestsForClassWithDefaultFactory(StandardDefaultFactoryTestCase.class, TempDirFactory.Standard.class) // .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("set to custom factory") void supportsCustomDefaultFactory() { executeTestsForClassWithDefaultFactory(NonStandardDefaultFactoryTestCase.class, Factory.class) // .assertStatistics(stats -> stats.started(1).succeeded(1)); } private static class Factory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory("junit"); } } } @Nested @DisplayName("reports failure") @TestMethodOrder(OrderAnnotation.class) class Failures { @Test @DisplayName("when @TempDir is used on static field of an unsupported type") @Order(20) void onlySupportsStaticFieldsOfTypePathAndFile() { var results = executeTestsForClass(AnnotationOnStaticFieldWithUnsupportedTypeTestCase.class); assertSingleFailedContainer(results, ExtensionConfigurationException.class, "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); } @Test @DisplayName("when @TempDir is used on instance field of an unsupported type") @Order(21) void onlySupportsInstanceFieldsOfTypePathAndFile() { var results = executeTestsForClass(AnnotationOnInstanceFieldWithUnsupportedTypeTestCase.class); assertSingleFailedTest(results, ExtensionConfigurationException.class, "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); } @Test @DisplayName("when @TempDir is used on parameter of an unsupported type") @Order(22) void onlySupportsParametersOfTypePathAndFile() { var results = executeTestsForClass(InvalidTestCase.class); // @formatter:off TempDirectoryPerContextTests.assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), message(m -> m.matches("Failed to resolve parameter \\[java.lang.String .+] in method \\[.+]: .+")), cause( instanceOf(ExtensionConfigurationException.class), message("Can only resolve @TempDir parameter of type java.nio.file.Path or java.io.File but was: java.lang.String"))); // @formatter:on } @Test @DisplayName("when @TempDir is used on constructor parameter") @Order(30) void doesNotSupportTempDirAnnotationOnConstructorParameter() { var results = executeTestsForClass(AnnotationOnConstructorParameterTestCase.class); assertSingleFailedTest(results, ParameterResolutionException.class, "@TempDir is not supported on constructor parameters. Please use field injection instead."); } @Test @DisplayName("when @TempDir is used on constructor parameter with @TestInstance(PER_CLASS)") @Order(31) void doesNotSupportTempDirAnnotationOnConstructorParameterWithTestInstancePerClass() { var results = executeTestsForClass(AnnotationOnConstructorParameterWithTestInstancePerClassTestCase.class); assertSingleFailedContainer(results, ParameterResolutionException.class, "@TempDir is not supported on constructor parameters. Please use field injection instead."); } @Test @DisplayName("when @TempDir factory is not Standard") @Order(32) void onlySupportsStandardTempDirFactory() { var results = executeTestsForClass(NonStandardFactoryTestCase.class); // @formatter:off TempDirectoryPerContextTests.assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")), cause( instanceOf(ExtensionConfigurationException.class), message("Custom @TempDir factory is not supported with junit.jupiter.tempdir.scope=per_context. " + "Use junit.jupiter.tempdir.factory.default instead."))); // @formatter:on } } @Nested @DisplayName("supports @TempDir") @TestMethodOrder(OrderAnnotation.class) class PrivateFields { @Test @DisplayName("on private static field") @Order(10) void supportsPrivateInstanceFields() { executeTestsForClass(AnnotationOnPrivateStaticFieldTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("on private instance field") @Order(11) void supportsPrivateStaticFields() { executeTestsForClass(AnnotationOnPrivateInstanceFieldTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } } private static void assertSingleFailedContainer(EngineExecutionResults results, Class clazz, String message) { assertSingleFailedContainer(results, instanceOf(clazz), message(actual -> actual.contains(message))); } @SafeVarargs @SuppressWarnings("varargs") private static void assertSingleFailedContainer(EngineExecutionResults results, Condition... conditions) { results.containerEvents()// .assertStatistics(stats -> stats.started(2).failed(1).succeeded(1))// .assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); } private static void assertSingleFailedTest(EngineExecutionResults results, Class clazz, String message) { assertSingleFailedTest(results, instanceOf(clazz), message(actual -> actual.contains(message))); } @SafeVarargs @SuppressWarnings("varargs") private static void assertSingleFailedTest(EngineExecutionResults results, Condition... conditions) { results.testEvents().assertStatistics(stats -> stats.started(1).failed(1).succeeded(0)); results.testEvents().assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); } private void assertSeparateTempDirsForFieldInjection( Class testClass) { assertResolvesSeparateTempDirs(testClass, BaseSeparateTempDirsFieldInjectionTestCase.tempDirs); } private void assertSeparateTempDirsForParameterInjection( Class testClass) { assertResolvesSeparateTempDirs(testClass, BaseSeparateTempDirsParameterInjectionTestCase.tempDirs); } private void assertResolvesSeparateTempDirs(Class testClass, Deque tempDirs) { var results = executeTestsForClass(testClass); results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); assertThat(tempDirs).hasSize(2); } // ------------------------------------------------------------------------- static class BaseSharedTempDirFieldInjectionTestCase { static Path staticTempDir; @TempDir Path tempDir; @BeforeEach void beforeEach(@TempDir Path tempDir) { if (BaseSharedTempDirFieldInjectionTestCase.staticTempDir != null) { assertSame(BaseSharedTempDirFieldInjectionTestCase.staticTempDir, tempDir); } else { BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; } check(tempDir); } @Test void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @Test void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @AfterEach void afterEach(@TempDir Path tempDir) { check(tempDir); } void check(Path tempDir) { assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir)// .isNotNull()// .isSameAs(tempDir)// .isSameAs(this.tempDir); assertTrue(Files.exists(tempDir)); } } static class AnnotationOnStaticFieldTestCase extends BaseSharedTempDirFieldInjectionTestCase { @TempDir static Path staticTempPath; @TempDir static File staticTempFile; @Override void check(Path tempDir) { assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir)// .isNotNull()// .isSameAs(AnnotationOnStaticFieldTestCase.staticTempPath)// .isSameAs(tempDir)// .isSameAs(this.tempDir); assertTrue(Files.exists(tempDir)); } } static class AnnotationOnStaticFieldAndBeforeAllMethodParameterTestCase extends AnnotationOnStaticFieldTestCase { @BeforeAll static void beforeAll(@TempDir Path tempDir) { assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir).isNull(); BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; assertThat(AnnotationOnStaticFieldTestCase.staticTempFile).isNotNull(); assertThat(AnnotationOnStaticFieldTestCase.staticTempPath)// .isNotNull()// .isSameAs(tempDir); assertThat(AnnotationOnStaticFieldTestCase.staticTempFile.toPath().toAbsolutePath())// .isEqualTo(AnnotationOnStaticFieldTestCase.staticTempPath.toAbsolutePath()); assertTrue(Files.exists(tempDir)); } } static class AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase extends BaseSharedTempDirFieldInjectionTestCase { @BeforeAll static void beforeAll(@TempDir Path tempDir) { assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir).isNull(); BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; assertTrue(Files.exists(tempDir)); } } @TestInstance(PER_CLASS) static class AnnotationOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClassTestCase extends AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase { } static class AnnotationOnPrivateInstanceFieldTestCase { @SuppressWarnings("unused") @TempDir private Path tempDir; @Test void test() { assertTrue(Files.exists(tempDir)); } } static class AnnotationOnPrivateStaticFieldTestCase { @SuppressWarnings("unused") @TempDir private static Path tempDir; @Test void test() { assertTrue(Files.exists(tempDir)); } } static class AnnotationOnStaticFieldWithUnsupportedTypeTestCase { @SuppressWarnings("unused") @TempDir static String tempDir; @Test void test1() { } } static class AnnotationOnInstanceFieldWithUnsupportedTypeTestCase { @SuppressWarnings("unused") @TempDir String tempDir; @Test void test1() { } } static class BaseSharedTempDirParameterInjectionTestCase { static Path tempDir; @BeforeEach void beforeEach(@TempDir Path tempDir) { check(tempDir); } @Test void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @Test void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @AfterEach void afterEach(@TempDir Path tempDir) { check(tempDir); } static void check(Path tempDir) { assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNotNull().isSameAs(tempDir); assertTrue(Files.exists(tempDir)); } } static class AnnotationOnConstructorParameterTestCase { AnnotationOnConstructorParameterTestCase(@SuppressWarnings("unused") @TempDir Path tempDir) { // never called } @Test void test() { // never called } } @TestInstance(PER_CLASS) static class AnnotationOnConstructorParameterWithTestInstancePerClassTestCase extends AnnotationOnConstructorParameterTestCase { AnnotationOnConstructorParameterWithTestInstancePerClassTestCase(@TempDir Path tempDir) { super(tempDir); } } static class NonStandardFactoryTestCase { @Test void test(@SuppressWarnings("unused") @TempDir(factory = Factory.class) Path tempDir) { // never called } private static class Factory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory("junit"); } } } static class StandardDefaultFactoryTestCase { @Test void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { assertSame(tempDir1, tempDir2); } } static class NonStandardDefaultFactoryTestCase { @Test void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { assertSame(tempDir1, tempDir2); } } static class AnnotationOnBeforeAllMethodParameterTestCase extends BaseSharedTempDirParameterInjectionTestCase { @BeforeAll static void beforeAll(@TempDir Path tempDir) { assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNull(); BaseSharedTempDirParameterInjectionTestCase.tempDir = tempDir; check(tempDir); } } @TestInstance(PER_CLASS) static class AnnotationOnBeforeAllMethodParameterWithTestInstancePerClassTestCase extends BaseSharedTempDirParameterInjectionTestCase { @BeforeAll void beforeAll(@TempDir Path tempDir) { assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNull(); BaseSharedTempDirParameterInjectionTestCase.tempDir = tempDir; check(tempDir); } } static class AnnotationOnAfterAllMethodParameterTestCase { static Path firstTempDir = null; static Path secondTempDir = null; @Test void test(@TempDir Path tempDir, TestInfo testInfo) throws Exception { assertThat(firstTempDir).isNull(); firstTempDir = tempDir; writeFile(tempDir, testInfo); } @AfterAll static void afterAll(@TempDir Path tempDir) { assertThat(firstTempDir).isNotNull(); assertNotEquals(firstTempDir, tempDir); secondTempDir = tempDir; } } static class BaseSeparateTempDirsFieldInjectionTestCase { static final Deque tempDirs = new LinkedList<>(); @TempDir Path tempDir; @BeforeEach void beforeEach(@TempDir Path tempDir) { for (Path dir : tempDirs) { assertThat(dir).doesNotExist(); } assertThat(tempDirs).doesNotContain(tempDir); tempDirs.add(tempDir); check(tempDir); } @Test void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @Test void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @AfterEach void afterEach(@TempDir Path tempDir) { check(tempDir); } void check(Path tempDir) { assertThat(tempDirs.getLast())// .isNotNull()// .isSameAs(tempDir)// .isSameAs(this.tempDir); assertTrue(Files.exists(tempDir)); } } static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase extends BaseSeparateTempDirsFieldInjectionTestCase { } @TestInstance(PER_CLASS) static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassFieldInjectionTestCase extends SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase { } static class BaseSeparateTempDirsParameterInjectionTestCase { static final Deque tempDirs = new LinkedList<>(); @BeforeEach void beforeEach(@TempDir Path tempDir) { for (Path dir : tempDirs) { assertThat(dir).doesNotExist(); } assertThat(tempDirs).doesNotContain(tempDir); tempDirs.add(tempDir); check(tempDir); } @Test void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @Test void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { check(tempDir); writeFile(tempDir, testInfo); } @AfterEach void afterEach(@TempDir Path tempDir) { check(tempDir); } void check(Path tempDir) { assertSame(tempDirs.getLast(), tempDir); assertTrue(Files.exists(tempDir)); } } static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase extends BaseSeparateTempDirsParameterInjectionTestCase { } @TestInstance(PER_CLASS) static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassParameterInjectionTestCase extends SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase { } static class InvalidTestCase { @Test void wrongParameterType(@SuppressWarnings("unused") @TempDir String ignored) { fail("this should never be called"); } } static class FileInjectionTestCase { @TempDir File fileTempDir; @TempDir Path pathTempDir; @Test void checkFile(@TempDir File tempDir, @TempDir Path ref) { assertFileAndPathAreEqual(tempDir, ref); assertFileAndPathAreEqual(this.fileTempDir, this.pathTempDir); } private void assertFileAndPathAreEqual(File tempDir, Path ref) { Path path = tempDir.toPath(); assertEquals(ref.toAbsolutePath(), path.toAbsolutePath()); assertTrue(Files.exists(path)); } } private static void writeFile(Path tempDir, TestInfo testInfo) throws IOException { Path file = tempDir.resolve(testInfo.getTestMethod().orElseThrow().getName() + ".txt"); Files.write(file, testInfo.getDisplayName().getBytes()); } // https://github.com/junit-team/junit5/issues/1748 static class TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase { TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase(TestInfo testInfo) { assertNotNull(testInfo); } @Test void test() { } } // https://github.com/junit-team/junit5/issues/1801 static class UserTempDirectoryDeletionDoesNotCauseFailureTestCase { @Test void deleteTempDir(@TempDir Path tempDir) throws IOException { Files.delete(tempDir); assertThat(tempDir).doesNotExist(); } } // https://github.com/junit-team/junit5/issues/2046 static class NonWritableFileDoesNotCauseFailureTestCase { @Test void createReadonlyFile(@TempDir Path tempDir) throws IOException { // Removal of setWritable(false) files might fail (e.g. for Windows) // The test verifies that @TempDir is capable of removing of such files var path = Files.write(tempDir.resolve("test.txt"), new byte[0]); assumeTrue(path.toFile().setWritable(false), () -> "Unable to set file " + path + " readonly via .toFile().setWritable(false)"); } } // https://github.com/junit-team/junit5/issues/2171 static class ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase { @Test void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { File file = tempDir.toPath().resolve("file").toFile(); assumeTrue(file.createNewFile()); assumeTrue(makeReadOnly(tempDir)); assumeTrue(makeReadOnly(file)); } } // https://github.com/junit-team/junit5/issues/2171 static class ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase { @Test void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { File file = tempDir.toPath().resolve("dir").resolve("file").toFile(); assumeTrue(file.getParentFile().mkdirs()); assumeTrue(file.createNewFile()); assumeTrue(makeReadOnly(tempDir)); assumeTrue(makeReadOnly(file.getParentFile())); assumeTrue(makeReadOnly(file)); } } private static boolean makeReadOnly(File file) throws IOException { var dos = Files.getFileAttributeView(file.toPath(), DosFileAttributeView.class); if (dos != null) { dos.setReadOnly(true); return true; } return file.setReadOnly(); } // https://github.com/junit-team/junit5/issues/2609 @SuppressWarnings("ResultOfMethodCallIgnored") static class NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase { @Test void createFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile(); } @Test void createFolder(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile(); } @Test void createNonWritableFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); } @Test void createNonReadableFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); } @Test void createNonWritableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); } @Test void createNonReadableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); } @Test void createNonExecutableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); } @Test void createNonEmptyNonWritableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); } @Test void createNonEmptyNonReadableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); } @Test void createNonEmptyNonExecutableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); } @Test void createNonEmptyDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); } @Test void createNonEmptyDirectoryWithNonWritableFile(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); } @Test void createNonEmptyDirectoryWithNonReadableFile(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); } } // https://github.com/junit-team/junit5/issues/2609 @SuppressWarnings("ResultOfMethodCallIgnored") static class NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase { @Nested class NonWritable { @Test void makeEmptyTempDirectoryNonWritable(@TempDir Path tempDir) { tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonWritableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonReadableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } } @Nested class NonReadable { @Test void makeEmptyTempDirectoryNonReadable(@TempDir Path tempDir) { tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonWritableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonReadableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } } @Nested class NonExecutable { @Test void makeEmptyTempDirectoryNonExecutable(@TempDir Path tempDir) { tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonWritableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonReadableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } } } // https://github.com/junit-team/junit5/issues/2079 static class TempDirUsageInsideNestedClassesTestCase { @TempDir File tempDir; @Test void topLevel() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } @Nested class NestedTestClass { @Test void nested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } @Nested class EvenDeeperNestedTestClass { @Test void deeplyNested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } } } } static class StaticTempDirUsageInsideNestedClassTestCase { @TempDir static File tempDir; static File initialTempDir; @Test void topLevel() { assertNotNull(tempDir); assertTrue(tempDir.exists()); initialTempDir = tempDir; } @Nested class NestedTestClass { @Test void nested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); assertSame(initialTempDir, tempDir); } } } } TempDirectoryPerDeclarationTests.java000066400000000000000000001355051455764576500401040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.cause; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.suppressed; import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Parameter; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Stream; import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.io.TempDirFactory.Standard; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.Constants; import org.junit.jupiter.engine.extension.TempDirectory.FileOperations; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for the new behavior of the {@link TempDirectory} extension * to create separate temp directories for each {@link TempDir} declaration. * * @since 5.8 */ @DisplayName("TempDirectory extension (per declaration)") class TempDirectoryPerDeclarationTests extends AbstractJupiterTestEngineTests { @BeforeEach @AfterEach void resetStaticVariables() { AllPossibleDeclarationLocationsTestCase.tempDirs.clear(); } @TestFactory @DisplayName("resolves separate temp dirs for each annotation declaration") Stream resolvesSeparateTempDirsForEachAnnotationDeclaration() { return Arrays.stream(TestInstance.Lifecycle.values()).map( lifecycle -> dynamicTest("with " + lifecycle + " lifecycle", () -> { var results = executeTests(request() // .selectors(selectClass(AllPossibleDeclarationLocationsTestCase.class)) // .configurationParameter(Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME, lifecycle.name()).build()); results.containerEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); results.testEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); assertThat(AllPossibleDeclarationLocationsTestCase.tempDirs).hasSize(3); var classTempDirs = AllPossibleDeclarationLocationsTestCase.tempDirs.get("class"); assertThat(classTempDirs).containsOnlyKeys("staticField1", "staticField2", "beforeAll1", "beforeAll2", "afterAll1", "afterAll2"); assertThat(classTempDirs.values()).hasSize(6).doesNotHaveDuplicates(); var testATempDirs = AllPossibleDeclarationLocationsTestCase.tempDirs.get("testA"); assertThat(testATempDirs).containsOnlyKeys("staticField1", "staticField2", "instanceField1", "instanceField2", "beforeEach1", "beforeEach2", "test1", "test2", "afterEach1", "afterEach2"); assertThat(testATempDirs.values()).hasSize(10).doesNotHaveDuplicates(); var testBTempDirs = AllPossibleDeclarationLocationsTestCase.tempDirs.get("testB"); assertThat(testBTempDirs).containsOnlyKeys("staticField1", "staticField2", "instanceField1", "instanceField2", "beforeEach1", "beforeEach2", "test1", "test2", "afterEach1", "afterEach2"); assertThat(testBTempDirs.values()).hasSize(10).doesNotHaveDuplicates(); assertThat(testATempDirs).containsEntry("staticField1", classTempDirs.get("staticField1")); assertThat(testBTempDirs).containsEntry("staticField1", classTempDirs.get("staticField1")); assertThat(testATempDirs).containsEntry("staticField2", classTempDirs.get("staticField2")); assertThat(testBTempDirs).containsEntry("staticField2", classTempDirs.get("staticField2")); assertThat(testATempDirs).doesNotContainEntry("instanceField1", testBTempDirs.get("instanceField1")); assertThat(testATempDirs).doesNotContainEntry("instanceField2", testBTempDirs.get("instanceField2")); assertThat(testATempDirs).doesNotContainEntry("beforeEach1", testBTempDirs.get("beforeEach1")); assertThat(testATempDirs).doesNotContainEntry("beforeEach2", testBTempDirs.get("beforeEach2")); assertThat(testATempDirs).doesNotContainEntry("test1", testBTempDirs.get("test1")); assertThat(testATempDirs).doesNotContainEntry("test2", testBTempDirs.get("test2")); assertThat(testATempDirs).doesNotContainEntry("afterEach1", testBTempDirs.get("afterEach1")); assertThat(testATempDirs).doesNotContainEntry("afterEach2", testBTempDirs.get("afterEach2")); })); } @Test @DisplayName("does not prevent constructor parameter resolution") void tempDirectoryDoesNotPreventConstructorParameterResolution() { executeTestsForClass(TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("does not prevent user from deleting the temp dir within a test") void tempDirectoryDoesNotPreventUserFromDeletingTempDir() { executeTestsForClass(UserTempDirectoryDeletionDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("is capable of removing a read-only file") void nonWritableFileDoesNotCauseFailure() { executeTestsForClass(NonWritableFileDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("is capable of removing non-executable, non-writable, or non-readable directories and folders") void nonMintPermissionsContentDoesNotCauseFailure() { executeTestsForClass(NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(13).succeeded(13)); } @Test @DisplayName("is capable of removing a directory when its permissions have been changed") void nonMintPermissionsDoNotCauseFailure() { executeTestsForClass(NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(42).succeeded(42)); } @Test @DisabledOnOs(OS.WINDOWS) @DisplayName("is capable of removing a read-only file in a read-only dir") void readOnlyFileInReadOnlyDirDoesNotCauseFailure() { executeTestsForClass(ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisabledOnOs(OS.WINDOWS) @DisplayName("is capable of removing a read-only file in a dir in a read-only dir") void readOnlyFileInNestedReadOnlyDirDoesNotCauseFailure() { executeTestsForClass(ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("can be used via instance field inside nested test classes") void canBeUsedViaInstanceFieldInsideNestedTestClasses() { executeTestsForClass(TempDirUsageInsideNestedClassesTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(3).succeeded(3)); } @Test @DisplayName("can be used via static field inside nested test classes") void canBeUsedViaStaticFieldInsideNestedTestClasses() { executeTestsForClass(StaticTempDirUsageInsideNestedClassTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); } @TestFactory @DisplayName("only attempts to delete undeletable paths once") Stream onlyAttemptsToDeleteUndeletablePathsOnce() { return Stream.of( // dynamicTest("directory", () -> onlyAttemptsToDeleteUndeletablePathOnce(UndeletableDirectoryTestCase.class)), // dynamicTest("file", () -> onlyAttemptsToDeleteUndeletablePathOnce(UndeletableFileTestCase.class)) // ); } private void onlyAttemptsToDeleteUndeletablePathOnce(Class testClass) { var results = executeTestsForClass(testClass); var tempDir = results.testEvents().reportingEntryPublished().stream().map( it -> it.getPayload(ReportEntry.class).orElseThrow()).map( it -> Path.of(it.getKeyValuePairs().get(UndeletableTestCase.TEMP_DIR))).findAny().orElseThrow(); assertSingleFailedTest(results, // instanceOf(IOException.class), // message("Failed to delete temp directory " + tempDir.toAbsolutePath() + ". " + // "The following paths could not be deleted (see suppressed exceptions for details): , undeletable"), // suppressed(0, instanceOf(DirectoryNotEmptyException.class)), // suppressed(1, instanceOf(IOException.class), message("Simulated failure"))); } @Nested @DisplayName("reports failure") @TestMethodOrder(OrderAnnotation.class) class Failures { @Test @DisplayName("when @TempDir is used on static field of an unsupported type") @Order(20) void onlySupportsStaticFieldsOfTypePathAndFile() { var results = executeTestsForClass(AnnotationOnStaticFieldWithUnsupportedTypeTestCase.class); assertSingleFailedContainer(results, ExtensionConfigurationException.class, "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); } @Test @DisplayName("when @TempDir is used on instance field of an unsupported type") @Order(21) void onlySupportsInstanceFieldsOfTypePathAndFile() { var results = executeTestsForClass(AnnotationOnInstanceFieldWithUnsupportedTypeTestCase.class); assertSingleFailedTest(results, ExtensionConfigurationException.class, "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); } @Test @DisplayName("when @TempDir is used on parameter of an unsupported type") @Order(22) void onlySupportsParametersOfTypePathAndFile() { var results = executeTestsForClass(InvalidTestCase.class); // @formatter:off TempDirectoryPerDeclarationTests.assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), message(m -> m.matches("Failed to resolve parameter \\[java.lang.String .+] in method \\[.+]: .+")), cause( instanceOf(ExtensionConfigurationException.class), message("Can only resolve @TempDir parameter of type java.nio.file.Path or java.io.File but was: java.lang.String"))); // @formatter:on } @Test @DisplayName("when @TempDir is used on constructor parameter") @Order(30) void doesNotSupportTempDirAnnotationOnConstructorParameter() { var results = executeTestsForClass(AnnotationOnConstructorParameterTestCase.class); assertSingleFailedTest(results, ParameterResolutionException.class, "@TempDir is not supported on constructor parameters. Please use field injection instead."); } @Test @DisplayName("when @TempDir is used on constructor parameter with @TestInstance(PER_CLASS)") @Order(31) void doesNotSupportTempDirAnnotationOnConstructorParameterWithTestInstancePerClass() { var results = executeTestsForClass(AnnotationOnConstructorParameterWithTestInstancePerClassTestCase.class); assertSingleFailedContainer(results, ParameterResolutionException.class, "@TempDir is not supported on constructor parameters. Please use field injection instead."); } } @Nested @DisplayName("supports @TempDir") @TestMethodOrder(OrderAnnotation.class) class PrivateFields { @Test @DisplayName("on private static field") @Order(10) void supportsPrivateInstanceFields() { executeTestsForClass(AnnotationOnPrivateStaticFieldTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("on private instance field") @Order(11) void supportsPrivateStaticFields() { executeTestsForClass(AnnotationOnPrivateInstanceFieldTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } } @Nested @DisplayName("supports custom factory") class Factory { @Test @DisplayName("that uses test method name as temp dir name prefix") void supportsFactoryWithTestMethodNameAsPrefix() { executeTestsForClass(FactoryWithTestMethodNameAsPrefixTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("that uses custom temp dir parent directory") void supportsFactoryWithCustomParentDirectory() { executeTestsForClass(FactoryWithCustomParentDirectoryTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("that uses com.github.marschall:memoryfilesystem") void supportsFactoryWithMemoryFileSystem() { executeTestsForClass(FactoryWithMemoryFileSystemTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("that uses com.google.jimfs:jimfs") void supportsFactoryWithJimfs() { executeTestsForClass(FactoryWithJimfsTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("that uses annotated element name as temp dir name prefix") void supportsFactoryWithAnnotatedElementNameAsPrefix() { executeTestsForClass(FactoryWithAnnotatedElementNameAsPrefixTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("that uses custom meta-annotation") void supportsFactoryWithCustomMetaAnnotation() { executeTestsForClass(FactoryWithCustomMetaAnnotationTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } } @Nested @DisplayName("supports default factory") @TestMethodOrder(OrderAnnotation.class) class DefaultFactory { private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class testClass, Class factoryClass) { return TempDirectoryPerDeclarationTests.super.executeTests(request() // .selectors(selectClass(testClass)) // .configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) // .build()); } @Test @DisplayName("set to Jupiter's default") void supportsStandardDefaultFactory() { executeTestsForClassWithDefaultFactory(StandardDefaultFactoryTestCase.class, Standard.class) // .testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("set to custom factory") void supportsCustomDefaultFactory() { executeTestsForClassWithDefaultFactory(CustomDefaultFactoryTestCase.class, Factory.class) // .testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } @Test @DisplayName("set to custom factory together with declaration of Jupiter's default") void supportsCustomDefaultFactoryWithStandardFactoryOnDeclaration() { executeTestsForClassWithDefaultFactory( // CustomDefaultFactoryWithStandardDeclarationTestCase.class, Factory.class) // .testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); } private static class Factory implements TempDirFactory { private boolean closed; @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory("custom"); } @Override public void close() { if (closed) { throw new IllegalStateException("already closed"); } closed = true; } } } private static void assertSingleFailedContainer(EngineExecutionResults results, Class clazz, String message) { assertSingleFailedContainer(results, instanceOf(clazz), message(actual -> actual.contains(message))); } @SafeVarargs @SuppressWarnings("varargs") private static void assertSingleFailedContainer(EngineExecutionResults results, Condition... conditions) { results.containerEvents()// .assertStatistics(stats -> stats.started(2).failed(1).succeeded(1))// .assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); } private static void assertSingleFailedTest(EngineExecutionResults results, Class clazz, String message) { assertSingleFailedTest(results, instanceOf(clazz), message(actual -> actual.contains(message))); } @SafeVarargs @SuppressWarnings("varargs") private static void assertSingleFailedTest(EngineExecutionResults results, Condition... conditions) { results.testEvents().assertStatistics(stats -> stats.started(1).failed(1).succeeded(0)); results.testEvents().assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); } // ------------------------------------------------------------------------- static class AnnotationOnPrivateInstanceFieldTestCase { @SuppressWarnings("unused") @TempDir private Path tempDir; @Test void test() { assertTrue(Files.exists(tempDir)); } } static class AnnotationOnPrivateStaticFieldTestCase { @SuppressWarnings("unused") @TempDir private static Path tempDir; @Test void test() { assertTrue(Files.exists(tempDir)); } } static class AnnotationOnStaticFieldWithUnsupportedTypeTestCase { @SuppressWarnings("unused") @TempDir static String tempDir; @Test void test1() { } } static class AnnotationOnInstanceFieldWithUnsupportedTypeTestCase { @SuppressWarnings("unused") @TempDir String tempDir; @Test void test1() { } } static class AnnotationOnConstructorParameterTestCase { AnnotationOnConstructorParameterTestCase(@SuppressWarnings("unused") @TempDir Path tempDir) { // never called } @Test void test() { // never called } } @TestInstance(PER_CLASS) static class AnnotationOnConstructorParameterWithTestInstancePerClassTestCase extends AnnotationOnConstructorParameterTestCase { AnnotationOnConstructorParameterWithTestInstancePerClassTestCase(@TempDir Path tempDir) { super(tempDir); } } static class InvalidTestCase { @Test void wrongParameterType(@SuppressWarnings("unused") @TempDir String ignored) { fail("this should never be called"); } } @Nested @DisplayName("resolves java.io.File injection type") class FileAndPathInjection { @TempDir File fileTempDir; @TempDir Path pathTempDir; @Test @DisplayName("and injected File and Path do not reference the same temp directory") void checkFile(@TempDir File tempDir, @TempDir Path ref) { assertFileAndPathAreNotEqual(tempDir, ref); assertFileAndPathAreNotEqual(this.fileTempDir, this.pathTempDir); } private static void assertFileAndPathAreNotEqual(File tempDir, Path ref) { Path path = tempDir.toPath(); assertNotEquals(ref.toAbsolutePath(), path.toAbsolutePath()); assertTrue(Files.exists(path)); } } // https://github.com/junit-team/junit5/issues/1748 static class TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase { @TempDir Path tempDir; TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase(TestInfo testInfo) { assertNotNull(testInfo); } @Test void test() { assertNotNull(tempDir); } } // https://github.com/junit-team/junit5/issues/1801 static class UserTempDirectoryDeletionDoesNotCauseFailureTestCase { @Test void deleteTempDir(@TempDir Path tempDir) throws IOException { Files.delete(tempDir); assertThat(tempDir).doesNotExist(); } } // https://github.com/junit-team/junit5/issues/2046 static class NonWritableFileDoesNotCauseFailureTestCase { @Test void createReadonlyFile(@TempDir Path tempDir) throws IOException { // Removal of setWritable(false) files might fail (e.g. for Windows) // The test verifies that @TempDir is capable of removing of such files var path = Files.write(tempDir.resolve("test.txt"), new byte[0]); assumeTrue(path.toFile().setWritable(false), () -> "Unable to set file " + path + " readonly via .toFile().setWritable(false)"); } } // https://github.com/junit-team/junit5/issues/2171 static class ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase { @Test void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { File file = tempDir.toPath().resolve("file").toFile(); assumeTrue(file.createNewFile()); assumeTrue(tempDir.setReadOnly()); assumeTrue(file.setReadOnly()); } } // https://github.com/junit-team/junit5/issues/2171 static class ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase { @Test void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { File file = tempDir.toPath().resolve("dir").resolve("file").toFile(); assumeTrue(file.getParentFile().mkdirs()); assumeTrue(file.createNewFile()); assumeTrue(tempDir.setReadOnly()); assumeTrue(file.getParentFile().setReadOnly()); assumeTrue(file.setReadOnly()); } } // https://github.com/junit-team/junit5/issues/2609 @SuppressWarnings("ResultOfMethodCallIgnored") static class NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase { @Test void createFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile(); } @Test void createFolder(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile(); } @Test void createNonWritableFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); } @Test void createNonReadableFile(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); } @Test void createNonWritableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); } @Test void createNonReadableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); } @Test void createNonExecutableDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); } @Test void createNonEmptyNonWritableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); } @Test void createNonEmptyNonReadableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); } @Test void createNonEmptyNonExecutableDirectory(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); } @Test void createNonEmptyDirectory(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); } @Test void createNonEmptyDirectoryWithNonWritableFile(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); } @Test void createNonEmptyDirectoryWithNonReadableFile(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); } } // https://github.com/junit-team/junit5/issues/2609 @SuppressWarnings("ResultOfMethodCallIgnored") static class NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase { @Nested class NonWritable { @Test void makeEmptyTempDirectoryNonWritable(@TempDir Path tempDir) { tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonWritableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonReadableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setWritable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonWritable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setWritable(false); } } @Nested class NonReadable { @Test void makeEmptyTempDirectoryNonReadable(@TempDir Path tempDir) { tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonWritableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonReadableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setReadable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonReadable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setReadable(false); } } @Nested class NonExecutable { @Test void makeEmptyTempDirectoryNonExecutable(@TempDir Path tempDir) { tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonWritableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonReadableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonExecutableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setReadable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyNonExecutableFolderNonExecutable(@TempDir Path tempDir) throws IOException { Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); subDir.toFile().setExecutable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); tempDir.toFile().setExecutable(false); } @Test void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonExecutable(@TempDir Path tempDir) throws IOException { Files.createDirectory(tempDir.resolve("test-sub-dir")); Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); tempDir.toFile().setExecutable(false); } } } // https://github.com/junit-team/junit5/issues/2079 static class TempDirUsageInsideNestedClassesTestCase { @TempDir File tempDir; @Test void topLevel() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } @Nested class NestedTestClass { @Test void nested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } @Nested class EvenDeeperNestedTestClass { @Test void deeplyNested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); } } } } static class StaticTempDirUsageInsideNestedClassTestCase { @TempDir static File tempDir; static File initialTempDir; @Test void topLevel() { assertNotNull(tempDir); assertTrue(tempDir.exists()); initialTempDir = tempDir; } @Nested class NestedTestClass { @Test void nested() { assertNotNull(tempDir); assertTrue(tempDir.exists()); assertSame(initialTempDir, tempDir); } } } @DisplayName("class") static class AllPossibleDeclarationLocationsTestCase { static final Map> tempDirs = new HashMap<>(); @TempDir static Path staticField1; @TempDir static Path staticField2; @TempDir Path instanceField1; @TempDir Path instanceField2; @BeforeAll static void beforeAll(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "staticField1", staticField1, // "staticField2", staticField2, // "beforeAll1", param1, // "beforeAll2", param2 // )); } @BeforeEach void beforeEach(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "staticField1", staticField1, // "staticField2", staticField2, // "instanceField1", instanceField1, // "instanceField2", instanceField2, // "beforeEach1", param1, // "beforeEach2", param2 // )); } @Test @DisplayName("testA") void testA(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "test1", param1, // "test2", param2 // )); } @Test @DisplayName("testB") void testB(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "test1", param1, // "test2", param2 // )); } @AfterEach void afterEach(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "afterEach1", param1, // "afterEach2", param2 // )); } @AfterAll static void afterAll(@TempDir Path param1, @TempDir Path param2, TestInfo testInfo) { getTempDirs(testInfo).putAll(Map.of( // "afterAll1", param1, // "afterAll2", param2 // )); } private static Map getTempDirs(TestInfo testInfo) { return tempDirs.computeIfAbsent(testInfo.getDisplayName(), __ -> new LinkedHashMap<>()); } } static class UndeletableTestCase { static final Path UNDELETABLE_PATH = Path.of("undeletable"); static final String TEMP_DIR = "TEMP_DIR"; @RegisterExtension BeforeEachCallback injector = context -> context // .getStore(TempDirectory.NAMESPACE) // .put(TempDirectory.FILE_OPERATIONS_KEY, (FileOperations) path -> { if (path.endsWith(UNDELETABLE_PATH)) { throw new IOException("Simulated failure"); } else { Files.delete(path); } }); @TempDir Path tempDir; @BeforeEach void reportTempDir(TestReporter reporter) { reporter.publishEntry(TEMP_DIR, tempDir.toString()); } } static class UndeletableDirectoryTestCase extends UndeletableTestCase { @Test void test() throws Exception { Files.createDirectory(tempDir.resolve(UNDELETABLE_PATH)); } } static class UndeletableFileTestCase extends UndeletableTestCase { @Test void test() throws Exception { Files.createFile(tempDir.resolve(UNDELETABLE_PATH)); } } static class FactoryWithTestMethodNameAsPrefixTestCase { @Test void test(@TempDir(factory = Factory.class) Path tempDir) { assertTrue(Files.exists(tempDir)); assertThat(tempDir.getFileName()).asString().startsWith("test"); } private static class Factory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory(extensionContext.getRequiredTestMethod().getName()); } } } // https://github.com/junit-team/junit5/issues/2088 static class FactoryWithCustomParentDirectoryTestCase { @Test void test(@TempDir(factory = Factory.class) Path tempDir) { assertThat(tempDir).exists().hasParent(Factory.parent); assertThat(tempDir.getFileName()).asString().startsWith("prefix"); } private static class Factory implements TempDirFactory { private static Path parent; private Factory() throws IOException { parent = Files.createTempDirectory("parent"); } @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory(parent, "prefix"); } } } static class FactoryWithMemoryFileSystemTestCase { @Test void test(@TempDir(factory = Factory.class) Path tempDir) { assertThat(tempDir).exists().hasFileSystem(Factory.fileSystem); assertThat(tempDir.getFileName()).asString().startsWith("prefix"); } private static class Factory implements TempDirFactory { private static FileSystem fileSystem; @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { fileSystem = MemoryFileSystemBuilder.newEmpty().build(); return Files.createTempDirectory(fileSystem.getPath("/"), "prefix"); } @Override public void close() throws IOException { fileSystem.close(); fileSystem = null; } } } static class FactoryWithJimfsTestCase { @Test void test(@TempDir(factory = Factory.class) Path tempDir) { assertThat(tempDir).exists().hasFileSystem(Factory.fileSystem); assertThat(tempDir.getFileName()).asString().startsWith("prefix"); } private static class Factory implements TempDirFactory { private static FileSystem fileSystem; @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { fileSystem = Jimfs.newFileSystem(Configuration.unix()); return Files.createTempDirectory(fileSystem.getPath("/"), "prefix"); } @Override public void close() throws IOException { fileSystem.close(); fileSystem = null; } } } static class FactoryWithAnnotatedElementNameAsPrefixTestCase { @TempDir(factory = Factory.class) private Path tempDir1; @Test void test(@TempDir(factory = Factory.class) Path tempDir2) { assertThat(tempDir1.getFileName()).asString().startsWith("tempDir1"); assertThat(tempDir2.getFileName()).asString().startsWith("tempDir2"); } private static class Factory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { return Files.createTempDirectory(getName(elementContext.getAnnotatedElement())); } private static String getName(AnnotatedElement element) { return element instanceof Field ? ((Field) element).getName() : ((Parameter) element).getName(); } } } static class FactoryWithCustomMetaAnnotationTestCase { @TempDirForField private Path tempDir1; @Test void test(@TempDirForParameter Path tempDir2) { assertThat(tempDir1.getFileName()).asString().startsWith("field"); assertThat(tempDir2.getFileName()).asString().startsWith("parameter"); } @Target(ANNOTATION_TYPE) @Retention(RUNTIME) @TempDir(factory = FactoryWithCustomMetaAnnotationTestCase.Factory.class) private @interface TempDirWithPrefix { String value(); } @Target(FIELD) @Retention(RUNTIME) @TempDirWithPrefix("field") private @interface TempDirForField { } @Target(PARAMETER) @Retention(RUNTIME) @TempDirWithPrefix("parameter") private @interface TempDirForParameter { } private static class Factory implements TempDirFactory { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { String prefix = elementContext.findAnnotation(TempDirWithPrefix.class) // .map(TempDirWithPrefix::value).orElseThrow(); return Files.createTempDirectory(prefix); } } } static class StandardDefaultFactoryTestCase { @Test void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { assertNotSame(tempDir1, tempDir2); assertThat(tempDir1.getFileName()).asString().startsWith("junit"); assertThat(tempDir2.getFileName()).asString().startsWith("junit"); } } static class CustomDefaultFactoryTestCase { @Test void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { assertNotSame(tempDir1, tempDir2); assertThat(tempDir1.getFileName()).asString().startsWith("custom"); assertThat(tempDir2.getFileName()).asString().startsWith("custom"); } } static class CustomDefaultFactoryWithStandardDeclarationTestCase { @Test void test(@TempDir Path tempDir1, @TempDir(factory = Standard.class) Path tempDir2) { assertNotSame(tempDir1, tempDir2); assertThat(tempDir1.getFileName()).asString().startsWith("custom"); assertThat(tempDir2.getFileName()).asString().startsWith("junit"); } } } TempDirectoryPreconditionTests.java000066400000000000000000000110521455764576500376330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; /** * Integration tests for preconditions and assertions in the {@link TempDirectory} * extension. * * @since 5.9 */ class TempDirectoryPreconditionTests extends AbstractJupiterTestEngineTests { @Test @DisplayName("Valid and invalid @TempDir parameter types") void parameterTypes() { EngineExecutionResults executionResults = executeTestsForClass(ParameterTypeTestCase.class); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(2).failed(1).succeeded(1)); tests.succeeded().assertEventsMatchExactly(event(test("validTempDirType"), finishedSuccessfully())); // @formatter:off tests.failed().assertEventsMatchExactly(event(test("invalidTempDirType"), finishedWithFailure(instanceOf(ParameterResolutionException.class), message(""" Failed to resolve parameter [java.lang.String text] in method \ [void org.junit.jupiter.engine.extension.TempDirectoryPreconditionTests$ParameterTypeTestCase.invalidTempDirType(java.lang.String)]: \ Can only resolve @TempDir parameter of type java.nio.file.Path or java.io.File but was: java.lang.String\ """)))); // @formatter:on } @Test @DisplayName("final static @TempDir fields are not supported") void finalStaticFieldIsNotSupported() { EngineExecutionResults executionResults = executeTestsForClass(FinalStaticFieldTestCase.class); Events containers = executionResults.containerEvents(); containers.assertStatistics(stats -> stats.started(2).failed(1).succeeded(1)); containers.succeeded().assertEventsMatchExactly(event(container("junit-jupiter"), finishedSuccessfully())); containers.failed().assertEventsMatchExactly(event(container("FinalStaticFieldTestCase"), finishedWithFailure(instanceOf(ExtensionConfigurationException.class), message(""" @TempDir field [static final java.nio.file.Path \ org.junit.jupiter.engine.extension.TempDirectoryPreconditionTests$FinalStaticFieldTestCase.path] \ must not be declared as final.\ """)))); } @Test @DisplayName("final instance @TempDir fields are not supported") void finalInstanceFieldIsNotSupported() { EngineExecutionResults executionResults = executeTestsForClass(FinalInstanceFieldTestCase.class); Events tests = executionResults.testEvents(); tests.assertStatistics(stats -> stats.started(1).failed(1).succeeded(0)); tests.failed().assertEventsMatchExactly( event(test("test()"), finishedWithFailure(instanceOf(ExtensionConfigurationException.class), message(""" @TempDir field [final java.nio.file.Path \ org.junit.jupiter.engine.extension.TempDirectoryPreconditionTests$FinalInstanceFieldTestCase.path] \ must not be declared as final.\ """)))); } // ------------------------------------------------------------------- static class ParameterTypeTestCase { @Test void validTempDirType(@TempDir File file, @TempDir Path path) { } @Test void invalidTempDirType(@TempDir String text) { } } static class FinalStaticFieldTestCase { static final @TempDir Path path = Paths.get("."); @Test void test() { } } static class FinalInstanceFieldTestCase { final @TempDir Path path = Paths.get("."); @Test void test() { } } } TestExecutionExceptionHandlerTests.java000066400000000000000000000174171455764576500404560ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for {@link TestExecutionExceptionHandler}. * * @since 5.0 */ class TestExecutionExceptionHandlerTests extends AbstractJupiterTestEngineTests { static List handlerCalls = new ArrayList<>(); @BeforeEach void resetStatics() { handlerCalls.clear(); RethrowException.handleExceptionCalled = false; ConvertException.handleExceptionCalled = false; SwallowException.handleExceptionCalled = false; ShouldNotBeCalled.handleExceptionCalled = false; } @Test void exceptionHandlerRethrowsException() { LauncherDiscoveryRequest request = request().selectors(selectMethod(ATestCase.class, "testRethrow")).build(); EngineExecutionResults executionResults = executeTests(request); assertTrue(RethrowException.handleExceptionCalled, "TestExecutionExceptionHandler should have been called"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ATestCase.class), started()), // event(test("testRethrow"), started()), // event(test("testRethrow"), finishedWithFailure(instanceOf(IOException.class), message("checked"))), // event(container(ATestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void exceptionHandlerSwallowsException() { LauncherDiscoveryRequest request = request().selectors(selectMethod(ATestCase.class, "testSwallow")).build(); EngineExecutionResults executionResults = executeTests(request); assertTrue(SwallowException.handleExceptionCalled, "TestExecutionExceptionHandler should have been called"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ATestCase.class), started()), // event(test("testSwallow"), started()), // event(test("testSwallow"), finishedSuccessfully()), // event(container(ATestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void exceptionHandlerConvertsException() { LauncherDiscoveryRequest request = request().selectors(selectMethod(ATestCase.class, "testConvert")).build(); EngineExecutionResults executionResults = executeTests(request); assertTrue(ConvertException.handleExceptionCalled, "TestExecutionExceptionHandler should have been called"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ATestCase.class), started()), // event(test("testConvert"), started()), // event(test("testConvert"), finishedWithFailure(instanceOf(IOException.class), message("checked"))), // event(container(ATestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void severalHandlersAreCalledInOrder() { LauncherDiscoveryRequest request = request().selectors(selectMethod(ATestCase.class, "testSeveral")).build(); EngineExecutionResults executionResults = executeTests(request); assertTrue(ConvertException.handleExceptionCalled, "ConvertException should have been called"); assertTrue(RethrowException.handleExceptionCalled, "RethrowException should have been called"); assertTrue(SwallowException.handleExceptionCalled, "SwallowException should have been called"); assertFalse(ShouldNotBeCalled.handleExceptionCalled, "ShouldNotBeCalled should not have been called"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(ATestCase.class), started()), // event(test("testSeveral"), started()), // event(test("testSeveral"), finishedSuccessfully()), // event(container(ATestCase.class), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); assertEquals(Arrays.asList("convert", "rethrow", "swallow"), handlerCalls); } // ------------------------------------------------------------------- static class ATestCase { @Test @ExtendWith(RethrowException.class) void testRethrow() throws IOException { throw new IOException("checked"); } @Test @ExtendWith(SwallowException.class) void testSwallow() throws IOException { throw new IOException("checked"); } @Test @ExtendWith(ConvertException.class) void testConvert() { throw new RuntimeException("unchecked"); } @Test @ExtendWith(ShouldNotBeCalled.class) @ExtendWith(SwallowException.class) @ExtendWith(RethrowException.class) @ExtendWith(ConvertException.class) void testSeveral() { throw new RuntimeException("unchecked"); } } static class RethrowException implements TestExecutionExceptionHandler { static boolean handleExceptionCalled = false; @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { assertTrue(throwable instanceof IOException); handleExceptionCalled = true; handlerCalls.add("rethrow"); throw throwable; } } static class SwallowException implements TestExecutionExceptionHandler { static boolean handleExceptionCalled = false; @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) { assertTrue(throwable instanceof IOException); handleExceptionCalled = true; handlerCalls.add("swallow"); //swallow exception by not rethrowing it } } static class ConvertException implements TestExecutionExceptionHandler { static boolean handleExceptionCalled = false; @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { assertTrue(throwable instanceof RuntimeException); handleExceptionCalled = true; handlerCalls.add("convert"); throw new IOException("checked"); } } static class ShouldNotBeCalled implements TestExecutionExceptionHandler { static boolean handleExceptionCalled = false; @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) { handleExceptionCalled = true; } } } TestInfoParameterResolverTests.java000066400000000000000000000046721455764576500376130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; import java.util.Set; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; /** * Integration tests for {@link TestInfoParameterResolver}. * * @since 5.0 */ @Tag("class-tag") class TestInfoParameterResolverTests { private static List allDisplayNames = Arrays.asList("defaultDisplayName(TestInfo)", "custom display name", "getTags(TestInfo)", "customDisplayNameThatIsEmpty(TestInfo)"); @Test void defaultDisplayName(TestInfo testInfo) { assertEquals("defaultDisplayName(TestInfo)", testInfo.getDisplayName()); } @Test @DisplayName("custom display name") void providedDisplayName(TestInfo testInfo) { assertEquals("custom display name", testInfo.getDisplayName()); } // TODO Update test to expect an exception once #743 is fixed. @Test @DisplayName("") void customDisplayNameThatIsEmpty(TestInfo testInfo) { assertEquals("customDisplayNameThatIsEmpty(TestInfo)", testInfo.getDisplayName()); } @Test @Tag("method-tag") void getTags(TestInfo testInfo) { assertEquals(2, testInfo.getTags().size()); assertTrue(testInfo.getTags().contains("method-tag")); assertTrue(testInfo.getTags().contains("class-tag")); } @BeforeEach @AfterEach void beforeAndAfter(TestInfo testInfo) { assertThat(allDisplayNames).contains(testInfo.getDisplayName()); } @BeforeAll static void beforeAll(TestInfo testInfo) { Set tags = testInfo.getTags(); assertEquals(1, tags.size()); assertTrue(tags.contains("class-tag")); } @BeforeAll @AfterAll static void beforeAndAfterAll(TestInfo testInfo) { assertEquals(TestInfoParameterResolverTests.class.getSimpleName(), testInfo.getDisplayName()); } } TestInstanceFactoryTests.java000066400000000000000000000574641455764576500364400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.commons.util.ClassUtils.nullSafeToString; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.nestedContainer; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestInstanceFactory; import org.junit.jupiter.api.extension.TestInstanceFactoryContext; import org.junit.jupiter.api.extension.TestInstantiationException; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests that verify support for {@link TestInstanceFactory}. * * @since 5.3 */ class TestInstanceFactoryTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @BeforeEach void resetCallSequence() { callSequence.clear(); } @Test void multipleFactoriesRegisteredOnSingleTestClass() { Class testClass = MultipleFactoriesRegisteredOnSingleTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(ExtensionConfigurationException.class), message("The following TestInstanceFactory extensions were registered for test class [" + testClass.getName() + "], but only one is permitted: " + nullSafeToString(FooInstanceFactory.class, BarInstanceFactory.class)))), // event(engine(), finishedSuccessfully())); } @Test void multipleFactoriesRegisteredWithinTestClassHierarchy() { Class testClass = MultipleFactoriesRegisteredWithinClassHierarchyTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(ExtensionConfigurationException.class), message("The following TestInstanceFactory extensions were registered for test class [" + testClass.getName() + "], but only one is permitted: " + nullSafeToString(FooInstanceFactory.class, BarInstanceFactory.class)))), // event(engine(), finishedSuccessfully())); } @Test void multipleFactoriesRegisteredWithinNestedClassStructure() { Class outerClass = MultipleFactoriesRegisteredWithinNestedClassStructureTestCase.class; Class nestedClass = MultipleFactoriesRegisteredWithinNestedClassStructureTestCase.InnerTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(outerClass); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(outerClass), started()), // event(test("outerTest()"), started()), // event(test("outerTest()"), finishedSuccessfully()), // event(nestedContainer(nestedClass), started()), // event(nestedContainer(nestedClass), finishedWithFailure(instanceOf(ExtensionConfigurationException.class), message("The following TestInstanceFactory extensions were registered for test class [" + nestedClass.getName() + "], but only one is permitted: " + nullSafeToString(FooInstanceFactory.class, BarInstanceFactory.class)))), // event(container(outerClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void nullTestInstanceFactoryWithPerMethodLifecycle() { Class testClass = NullTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("testShouldNotBeCalled"), started()), // event(test("testShouldNotBeCalled"), finishedWithFailure(instanceOf(TestInstantiationException.class), message(m -> m.equals("TestInstanceFactory [" + NullTestInstanceFactory.class.getName() + "] failed to return an instance of [" + testClass.getName() + "] and instead returned an instance of [null].")))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void nullTestInstanceFactoryWithPerClassLifecycle() { Class testClass = PerClassLifecycleNullTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(TestInstantiationException.class), message(m -> m.equals("TestInstanceFactory [" + NullTestInstanceFactory.class.getName() + "] failed to return an instance of [" + testClass.getName() + "] and instead returned an instance of [null].")))), // event(engine(), finishedSuccessfully())); } @Test void bogusTestInstanceFactoryWithPerMethodLifecycle() { Class testClass = BogusTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("testShouldNotBeCalled"), started()), // event(test("testShouldNotBeCalled"), finishedWithFailure(instanceOf(TestInstantiationException.class), message(m -> m.equals("TestInstanceFactory [" + BogusTestInstanceFactory.class.getName() + "] failed to return an instance of [" + testClass.getName() + "] and instead returned an instance of [java.lang.String].")))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void bogusTestInstanceFactoryWithPerClassLifecycle() { Class testClass = PerClassLifecycleBogusTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(TestInstantiationException.class), message(m -> m.equals("TestInstanceFactory [" + BogusTestInstanceFactory.class.getName() + "] failed to return an instance of [" + testClass.getName() + "] and instead returned an instance of [java.lang.String].")))), // event(engine(), finishedSuccessfully())); } @Test void explosiveTestInstanceFactoryWithPerMethodLifecycle() { Class testClass = ExplosiveTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("testShouldNotBeCalled"), started()), // event(test("testShouldNotBeCalled"), finishedWithFailure(instanceOf(TestInstantiationException.class), message("TestInstanceFactory [" + ExplosiveTestInstanceFactory.class.getName() + "] failed to instantiate test class [" + testClass.getName() + "]: boom!"))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void explosiveTestInstanceFactoryWithPerClassLifecycle() { Class testClass = PerClassLifecycleExplosiveTestInstanceFactoryTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), // finishedWithFailure(instanceOf(TestInstantiationException.class), message("TestInstanceFactory [" + ExplosiveTestInstanceFactory.class.getName() + "] failed to instantiate test class [" + testClass.getName() + "]: boom!"))), // event(engine(), finishedSuccessfully())); } @Test void proxyTestInstanceFactoryFailsDueToUseOfDifferentClassLoader() { Class testClass = ProxiedTestCase.class; EngineExecutionResults executionResults = executeTestsForClass(testClass); assertEquals(0, executionResults.testEvents().started().count(), "# tests started"); assertEquals(0, executionResults.testEvents().failed().count(), "# tests aborted"); executionResults.allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), // // NOTE: the test class names are the same even though the objects are // instantiated using different ClassLoaders. Thus, we check for the // appended "@" but ignore the actual hash code for the test class // loaded by the different ClassLoader. finishedWithFailure(instanceOf(TestInstantiationException.class), message(m -> m.startsWith("TestInstanceFactory [" + ProxyTestInstanceFactory.class.getName() + "]") && m.contains("failed to return an instance of [" + testClass.getName() + "@" + Integer.toHexString(System.identityHashCode(testClass))) && m.contains("and instead returned an instance of [" + testClass.getName() + "@")// ))), // event(engine(), finishedSuccessfully())); } @Test void instanceFactoryOnTopLevelTestClass() { EngineExecutionResults executionResults = executeTestsForClass(ParentTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( "FooInstanceFactory instantiated: ParentTestCase", "parentTest" ); // @formatter:on } @Test void instanceFactorySupportedWhenTestClassDeclaresMultipleConstructors() { executeTestsForClass(MultipleConstructorsTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); // @formatter:off assertThat(callSequence).containsExactly( "MultipleConstructorsTestInstanceFactory instantiated: MultipleConstructorsTestCase", "test: 42" ); // @formatter:on } @Test void inheritedFactoryInTestClassHierarchy() { EngineExecutionResults executionResults = executeTestsForClass(InheritedFactoryTestCase.class); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( "FooInstanceFactory instantiated: InheritedFactoryTestCase", "parentTest", "FooInstanceFactory instantiated: InheritedFactoryTestCase", "childTest" ); // @formatter:on } @Test void instanceFactoriesInNestedClassStructureAreInherited() { EngineExecutionResults executionResults = executeTestsForClass(OuterTestCase.class); assertEquals(3, executionResults.testEvents().started().count(), "# tests started"); assertEquals(3, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( // OuterTestCase "FooInstanceFactory instantiated: OuterTestCase", "outerTest", // InnerTestCase "FooInstanceFactory instantiated: OuterTestCase", "FooInstanceFactory instantiated: InnerTestCase", "innerTest1", // InnerInnerTestCase "FooInstanceFactory instantiated: OuterTestCase", "FooInstanceFactory instantiated: InnerTestCase", "FooInstanceFactory instantiated: InnerInnerTestCase", "innerTest2" ); // @formatter:on } @Test void instanceFactoryRegisteredViaTestInterface() { EngineExecutionResults executionResults = executeTestsForClass(FactoryFromInterfaceTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( "FooInstanceFactory instantiated: FactoryFromInterfaceTestCase", "test" ); // @formatter:on } @Test void instanceFactoryRegisteredAsLambdaExpression() { EngineExecutionResults executionResults = executeTestsForClass(LambdaFactoryTestCase.class); assertEquals(1, executionResults.testEvents().started().count(), "# tests started"); assertEquals(1, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( "beforeEach: lambda", "test: lambda" ); // @formatter:on } @Test void instanceFactoryWithPerClassLifecycle() { EngineExecutionResults executionResults = executeTestsForClass(PerClassLifecycleTestCase.class); assertEquals(1, PerClassLifecycleTestCase.counter.get()); assertEquals(2, executionResults.testEvents().started().count(), "# tests started"); assertEquals(2, executionResults.testEvents().succeeded().count(), "# tests succeeded"); // @formatter:off assertThat(callSequence).containsExactly( "FooInstanceFactory instantiated: PerClassLifecycleTestCase", "@BeforeAll", "@BeforeEach", "test1", "@BeforeEach", "test2", "@AfterAll" ); // @formatter:on } // ------------------------------------------------------------------------- @ExtendWith({ FooInstanceFactory.class, BarInstanceFactory.class }) static class MultipleFactoriesRegisteredOnSingleTestCase { @Test void testShouldNotBeCalled() { callSequence.add("testShouldNotBeCalled"); } } @ExtendWith(NullTestInstanceFactory.class) static class NullTestInstanceFactoryTestCase { @Test void testShouldNotBeCalled() { callSequence.add("testShouldNotBeCalled"); } } @TestInstance(PER_CLASS) static class PerClassLifecycleNullTestInstanceFactoryTestCase extends NullTestInstanceFactoryTestCase { } @ExtendWith(BogusTestInstanceFactory.class) static class BogusTestInstanceFactoryTestCase { @Test void testShouldNotBeCalled() { callSequence.add("testShouldNotBeCalled"); } } @TestInstance(PER_CLASS) static class PerClassLifecycleBogusTestInstanceFactoryTestCase extends BogusTestInstanceFactoryTestCase { } @ExtendWith(ExplosiveTestInstanceFactory.class) static class ExplosiveTestInstanceFactoryTestCase { @Test void testShouldNotBeCalled() { callSequence.add("testShouldNotBeCalled"); } } @TestInstance(PER_CLASS) static class PerClassLifecycleExplosiveTestInstanceFactoryTestCase extends ExplosiveTestInstanceFactoryTestCase { } private static class MultipleConstructorsTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { instantiated(getClass(), factoryContext.getTestClass()); return new MultipleConstructorsTestCase(42); } } @ExtendWith(MultipleConstructorsTestInstanceFactory.class) static class MultipleConstructorsTestCase { private final int number; public MultipleConstructorsTestCase(String text) { this.number = -1; } public MultipleConstructorsTestCase(int number) { this.number = number; } @Test void test() { callSequence.add("test: " + this.number); } } @ExtendWith(FooInstanceFactory.class) static class ParentTestCase { @Test void parentTest() { callSequence.add("parentTest"); } } static class InheritedFactoryTestCase extends ParentTestCase { @Test void childTest() { callSequence.add("childTest"); } } @ExtendWith(BarInstanceFactory.class) static class MultipleFactoriesRegisteredWithinClassHierarchyTestCase extends ParentTestCase { @Test void childTest() { callSequence.add("childTest"); } } @ExtendWith(FooInstanceFactory.class) static class OuterTestCase { @Test void outerTest() { callSequence.add("outerTest"); } @Nested class InnerTestCase { @Test void innerTest1() { callSequence.add("innerTest1"); } @Nested class InnerInnerTestCase { @Test void innerTest2() { callSequence.add("innerTest2"); } } } } @ExtendWith(FooInstanceFactory.class) static class MultipleFactoriesRegisteredWithinNestedClassStructureTestCase { @Test void outerTest() { } @Nested @ExtendWith(BarInstanceFactory.class) class InnerTestCase { @Test void innerTest() { } } } @ExtendWith(FooInstanceFactory.class) interface TestInterface { } static class FactoryFromInterfaceTestCase implements TestInterface { @Test void test() { callSequence.add("test"); } } static class LambdaFactoryTestCase { private final String text; @RegisterExtension static final TestInstanceFactory factory = (__, ___) -> new LambdaFactoryTestCase("lambda"); LambdaFactoryTestCase(String text) { this.text = text; } @BeforeEach void beforeEach() { callSequence.add("beforeEach: " + this.text); } @Test void test() { callSequence.add("test: " + this.text); } } @ExtendWith(FooInstanceFactory.class) @TestInstance(PER_CLASS) static class PerClassLifecycleTestCase { static final AtomicInteger counter = new AtomicInteger(); PerClassLifecycleTestCase() { counter.incrementAndGet(); } @BeforeAll void beforeAll() { callSequence.add("@BeforeAll"); } @BeforeEach void beforeEach() { callSequence.add("@BeforeEach"); } @Test void test1() { callSequence.add("test1"); } @Test void test2() { callSequence.add("test2"); } @AfterAll void afterAll() { callSequence.add("@AfterAll"); } } @ExtendWith(ProxyTestInstanceFactory.class) @TestInstance(PER_CLASS) static class ProxiedTestCase { @Test void test1() { callSequence.add("test1"); } @Test void test2() { callSequence.add("test2"); } } // ------------------------------------------------------------------------- private static abstract class AbstractTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { Class testClass = factoryContext.getTestClass(); instantiated(getClass(), testClass); if (factoryContext.getOuterInstance().isPresent()) { return ReflectionUtils.newInstance(testClass, factoryContext.getOuterInstance().get()); } // else return ReflectionUtils.newInstance(testClass); } } private static class FooInstanceFactory extends AbstractTestInstanceFactory { } private static class BarInstanceFactory extends AbstractTestInstanceFactory { } /** * {@link TestInstanceFactory} that returns null. */ private static class NullTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { return null; } } /** * {@link TestInstanceFactory} that returns an object of a type that does * not match the supplied test class. */ private static class BogusTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { return "bogus"; } } /** * {@link TestInstanceFactory} that always throws an exception. */ private static class ExplosiveTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { throw new RuntimeException("boom!"); } } /** * This does not actually create a proxy. Rather, it simulates what * a proxy-based implementation might do, by loading the class from a * different {@link ClassLoader}. */ private static class ProxyTestInstanceFactory implements TestInstanceFactory { @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { Class testClass = factoryContext.getTestClass(); String className = testClass.getName(); instantiated(getClass(), testClass); try (var testClassLoader = TestClassLoader.forClasses(testClass)) { // Load test class from different class loader Class clazz = testClassLoader.loadClass(className); return ReflectionUtils.newInstance(clazz); } catch (Exception ex) { throw new RuntimeException("Failed to load class [" + className + "]", ex); } } } private static boolean instantiated(Class factoryClass, Class testClass) { return callSequence.add(factoryClass.getSimpleName() + " instantiated: " + testClass.getSimpleName()); } } TestInstancePostProcessorAndPreDestroyCallbackTests.java000066400000000000000000000161651455764576500437300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; /** * Integration tests that verify support for {@link TestInstancePostProcessor} * and {@link TestInstancePreDestroyCallback} in the {@link JupiterTestEngine}. * * @since 5.6 */ class TestInstancePostProcessorAndPreDestroyCallbackTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @Test void postProcessorAndPreDestroyCallbacks() { // @formatter:off assertPostProcessorAndPreDestroyCallbacks(TopLevelTestCase.class, "fooPostProcessTestInstance", "barPostProcessTestInstance", "test-1", "barPreDestroyTestInstance", "fooPreDestroyTestInstance" ); // @formatter:on } @Test void postProcessorAndPreDestroyCallbacksInSubclass() { // @formatter:off assertPostProcessorAndPreDestroyCallbacks(SecondLevelTestCase.class, "fooPostProcessTestInstance", "barPostProcessTestInstance", "bazPostProcessTestInstance", "test-2", "bazPreDestroyTestInstance", "barPreDestroyTestInstance", "fooPreDestroyTestInstance" ); // @formatter:on } @Test void postProcessorAndPreDestroyCallbacksInSubSubclass() { // @formatter:off assertPostProcessorAndPreDestroyCallbacks(ThirdLevelTestCase.class, "fooPostProcessTestInstance", "barPostProcessTestInstance", "bazPostProcessTestInstance", "quuxPostProcessTestInstance", "test-3", "quuxPreDestroyTestInstance", "bazPreDestroyTestInstance", "barPreDestroyTestInstance", "fooPreDestroyTestInstance" ); // @formatter:on } @Test void preDestroyTestInstanceMethodThrowsAnException() { // @formatter:off assertPostProcessorAndPreDestroyCallbacks(ExceptionInTestInstancePreDestroyCallbackTestCase.class, 0, "fooPostProcessTestInstance", "test", "exceptionThrowingTestInstancePreDestroyCallback" ); // @formatter:on } @Test void postProcessTestInstanceMethodThrowsAnException() { assertPostProcessorAndPreDestroyCallbacks(ExceptionInTestInstancePostProcessorTestCase.class, 0, "exceptionThrowingTestInstancePostProcessor", "exceptionPreDestroyTestInstance"); } @Test void testClassConstructorThrowsAnException() { assertPostProcessorAndPreDestroyCallbacks(ExceptionInTestClassConstructorTestCase.class, 0, "exceptionThrowingConstructor"); } private void assertPostProcessorAndPreDestroyCallbacks(Class testClass, String... expectedCalls) { assertPostProcessorAndPreDestroyCallbacks(testClass, 1, expectedCalls); } private void assertPostProcessorAndPreDestroyCallbacks(Class testClass, int testsSuccessful, String... expectedCalls) { callSequence.clear(); executeTestsForClass(testClass).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(testsSuccessful)); assertEquals(asList(expectedCalls), callSequence, () -> "wrong call sequence for " + testClass.getName()); } // ------------------------------------------------------------------------- // Must NOT be private; otherwise, the @Test method gets discovered but never executed. @ExtendWith({ FooTestInstanceCallbacks.class, BarTestInstanceCallbacks.class }) static class TopLevelTestCase { @Test void test() { callSequence.add("test-1"); } } // Must NOT be private; otherwise, the @Test method gets discovered but never executed. @ExtendWith(BazTestInstanceCallbacks.class) static class SecondLevelTestCase extends TopLevelTestCase { @Test @Override void test() { callSequence.add("test-2"); } } @ExtendWith(QuuxTestInstanceCallbacks.class) static class ThirdLevelTestCase extends SecondLevelTestCase { @Test @Override void test() { callSequence.add("test-3"); } } @ExtendWith(ExceptionThrowingTestInstancePreDestroyCallback.class) static class ExceptionInTestInstancePreDestroyCallbackTestCase { @Test void test() { callSequence.add("test"); } } @ExtendWith(ExceptionThrowingTestInstancePostProcessor.class) static class ExceptionInTestInstancePostProcessorTestCase { @Test void test() { callSequence.add("test"); } } @ExtendWith(FooTestInstanceCallbacks.class) static class ExceptionInTestClassConstructorTestCase { ExceptionInTestClassConstructorTestCase() { callSequence.add("exceptionThrowingConstructor"); throw new RuntimeException("in constructor"); } @Test void test() { callSequence.add("test"); } } // ------------------------------------------------------------------------- static class FooTestInstanceCallbacks extends AbstractTestInstanceCallbacks { protected FooTestInstanceCallbacks() { super("foo"); } } static class BarTestInstanceCallbacks extends AbstractTestInstanceCallbacks { protected BarTestInstanceCallbacks() { super("bar"); } } static class BazTestInstanceCallbacks extends AbstractTestInstanceCallbacks { protected BazTestInstanceCallbacks() { super("baz"); } } static class QuuxTestInstanceCallbacks extends AbstractTestInstanceCallbacks { protected QuuxTestInstanceCallbacks() { super("quux"); } } static class ExceptionThrowingTestInstancePreDestroyCallback extends AbstractTestInstanceCallbacks { protected ExceptionThrowingTestInstancePreDestroyCallback() { super("foo"); } @Override public void preDestroyTestInstance(ExtensionContext context) { callSequence.add("exceptionThrowingTestInstancePreDestroyCallback"); throw new EnigmaException("preDestroyTestInstance"); } } static class ExceptionThrowingTestInstancePostProcessor extends AbstractTestInstanceCallbacks { protected ExceptionThrowingTestInstancePostProcessor() { super("exception"); } @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { callSequence.add("exceptionThrowingTestInstancePostProcessor"); throw new EnigmaException("postProcessTestInstance"); } } private static abstract class AbstractTestInstanceCallbacks implements TestInstancePostProcessor, TestInstancePreDestroyCallback { private final String name; AbstractTestInstanceCallbacks(String name) { this.name = name; } @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { callSequence.add(name + "PostProcessTestInstance"); } @Override public void preDestroyTestInstance(ExtensionContext context) { callSequence.add(name + "PreDestroyTestInstance"); } } } TestInstancePostProcessorTests.java000066400000000000000000000107431455764576500376430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; /** * Integration tests that verify support for {@link TestInstancePostProcessor}. * * @since 5.0 */ class TestInstancePostProcessorTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @BeforeEach void resetCallSequence() { callSequence.clear(); } @Test void instancePostProcessorsInNestedClasses() { executeTestsForClass(OuterTestCase.class).testEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( // OuterTestCase "fooPostProcessTestInstance:OuterTestCase", "beforeOuterMethod", "testOuter", // InnerTestCase "fooPostProcessTestInstance:OuterTestCase", "fooPostProcessTestInstance:InnerTestCase", "barPostProcessTestInstance:InnerTestCase", "beforeOuterMethod", "beforeInnerMethod", "testInner" ); // @formatter:on } @Test void testSpecificTestInstancePostProcessorIsCalled() { executeTestsForClass(TestCaseWithTestSpecificTestInstancePostProcessor.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); assertThat(callSequence).containsExactly( "fooPostProcessTestInstance:TestCaseWithTestSpecificTestInstancePostProcessor", "beforeEachMethod", "test"); } // ------------------------------------------------------------------- @ExtendWith(FooInstancePostProcessor.class) static class OuterTestCase implements Named { private String outerName; @Override public void setName(String name) { this.outerName = name; } @BeforeEach void beforeOuterMethod() { callSequence.add("beforeOuterMethod"); } @Test void testOuter() { assertEquals("foo:" + OuterTestCase.class.getSimpleName(), outerName); callSequence.add("testOuter"); } @Nested @ExtendWith(BarInstancePostProcessor.class) class InnerTestCase implements Named { private String innerName; @Override public void setName(String name) { this.innerName = name; } @BeforeEach void beforeInnerMethod() { callSequence.add("beforeInnerMethod"); } @Test void testInner() { assertEquals("foo:" + OuterTestCase.class.getSimpleName(), outerName); assertEquals("bar:" + InnerTestCase.class.getSimpleName(), innerName); callSequence.add("testInner"); } } } static class TestCaseWithTestSpecificTestInstancePostProcessor implements Named { private String name; @Override public void setName(String name) { this.name = name; } @BeforeEach void beforeEachMethod() { callSequence.add("beforeEachMethod"); } @ExtendWith(FooInstancePostProcessor.class) @Test void test() { callSequence.add("test"); assertEquals("foo:" + getClass().getSimpleName(), name); } } static class FooInstancePostProcessor implements TestInstancePostProcessor { @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { if (testInstance instanceof Named) { ((Named) testInstance).setName("foo:" + context.getRequiredTestClass().getSimpleName()); } callSequence.add("fooPostProcessTestInstance:" + testInstance.getClass().getSimpleName()); } } static class BarInstancePostProcessor implements TestInstancePostProcessor { @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { if (testInstance instanceof Named) { ((Named) testInstance).setName("bar:" + context.getRequiredTestClass().getSimpleName()); } callSequence.add("barPostProcessTestInstance:" + testInstance.getClass().getSimpleName()); } } private interface Named { void setName(String name); } } TestInstancePreConstructCallbackTests.java000066400000000000000000000237001455764576500410630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestInstanceFactory; import org.junit.jupiter.api.extension.TestInstanceFactoryContext; import org.junit.jupiter.api.extension.TestInstancePreConstructCallback; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; /** * Integration tests that verify support for {@link TestInstancePreConstructCallback}. * * @since 5.9 */ class TestInstancePreConstructCallbackTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @BeforeEach void resetCallSequence() { callSequence.clear(); } @Test void instancePreConstruct() { executeTestsForClass(InstancePreConstructTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( "beforeAll", "PreConstructCallback: name=foo, testClass=InstancePreConstructTestCase, outerInstance: null", "constructor", "beforeEach", "test1", "afterEach", "PreConstructCallback: name=foo, testClass=InstancePreConstructTestCase, outerInstance: null", "constructor", "beforeEach", "test2", "afterEach", "afterAll" ); // @formatter:on } @Test void factoryPreConstruct() { executeTestsForClass(FactoryPreConstructTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( "beforeAll", "PreConstructCallback: name=foo, testClass=FactoryPreConstructTestCase, outerInstance: null", "testInstanceFactory", "constructor", "beforeEach", "test1", "afterEach", "PreConstructCallback: name=foo, testClass=FactoryPreConstructTestCase, outerInstance: null", "testInstanceFactory", "constructor", "beforeEach", "test2", "afterEach", "afterAll" ); // @formatter:on } @Test void preConstructInNested() { executeTestsForClass(PreConstructInNestedTestCase.class).testEvents()// .assertStatistics(stats -> stats.started(3).succeeded(3)); // @formatter:off assertThat(callSequence).containsExactly( "beforeAll", "PreConstructCallback: name=foo, testClass=PreConstructInNestedTestCase, outerInstance: null", "constructor", "beforeEach", "outerTest1", "afterEach", "PreConstructCallback: name=foo, testClass=PreConstructInNestedTestCase, outerInstance: null", "constructor", "beforeEach", "outerTest2", "afterEach", "PreConstructCallback: name=foo, testClass=PreConstructInNestedTestCase, outerInstance: null", "constructor", "PreConstructCallback: name=foo, testClass=InnerTestCase, outerInstance: #3", "PreConstructCallback: name=bar, testClass=InnerTestCase, outerInstance: #3", "PreConstructCallback: name=baz, testClass=InnerTestCase, outerInstance: #3", "constructorInner", "beforeEach", "beforeEachInner", "innerTest1", "afterEachInner", "afterEach", "afterAll" ); // @formatter:on } @Test void preConstructOnMethod() { executeTestsForClass(PreConstructOnMethod.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( "PreConstructCallback: name=foo, testClass=PreConstructOnMethod, outerInstance: null", "constructor", "beforeEach", "test1", "afterEach", "constructor", "beforeEach", "test2", "afterEach" ); // @formatter:on } @Test void preConstructWithClassLifecycle() { executeTestsForClass(PreConstructWithClassLifecycle.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( "PreConstructCallback: name=foo, testClass=PreConstructWithClassLifecycle, outerInstance: null", "PreConstructCallback: name=bar, testClass=PreConstructWithClassLifecycle, outerInstance: null", "constructor", "beforeEach", "test1", "beforeEach", "test2" ); // @formatter:on } private abstract static class CallSequenceRecordingTestCase { protected static void record(String event) { callSequence.add(event); } } @ExtendWith(InstancePreConstructCallbackRecordingFoo.class) static class InstancePreConstructTestCase extends CallSequenceRecordingTestCase { InstancePreConstructTestCase() { record("constructor"); } @BeforeAll static void beforeAll() { record("beforeAll"); } @BeforeEach void beforeEach() { record("beforeEach"); } @Test void test1() { record("test1"); } @Test void test2() { record("test2"); } @AfterEach void afterEach() { record("afterEach"); } @AfterAll static void afterAll() { record("afterAll"); } } @ExtendWith(InstancePreConstructCallbackRecordingFoo.class) static class FactoryPreConstructTestCase extends CallSequenceRecordingTestCase { @RegisterExtension static final TestInstanceFactory factory = (factoryContext, extensionContext) -> { record("testInstanceFactory"); return new FactoryPreConstructTestCase(); }; FactoryPreConstructTestCase() { record("constructor"); } @BeforeAll static void beforeAll() { record("beforeAll"); } @BeforeEach void beforeEach() { record("beforeEach"); } @Test void test1() { record("test1"); } @Test void test2() { record("test2"); } @AfterEach void afterEach() { record("afterEach"); } @AfterAll static void afterAll() { record("afterAll"); } } @ExtendWith(InstancePreConstructCallbackRecordingFoo.class) static class PreConstructInNestedTestCase extends CallSequenceRecordingTestCase { static AtomicInteger instanceCounter = new AtomicInteger(); private final String instanceId; PreConstructInNestedTestCase() { record("constructor"); instanceId = "#" + instanceCounter.incrementAndGet(); } @BeforeAll static void beforeAll() { instanceCounter.set(0); record("beforeAll"); } @BeforeEach void beforeEach() { record("beforeEach"); } @Test void outerTest1() { record("outerTest1"); } @Test void outerTest2() { record("outerTest2"); } @AfterEach void afterEach() { record("afterEach"); } @AfterAll static void afterAll() { record("afterAll"); } @Override public String toString() { return instanceId; } @ExtendWith(InstancePreConstructCallbackRecordingBar.class) abstract class InnerParent extends CallSequenceRecordingTestCase { } @Nested @ExtendWith(InstancePreConstructCallbackRecordingBaz.class) class InnerTestCase extends InnerParent { InnerTestCase() { record("constructorInner"); } @BeforeEach void beforeEachInner() { record("beforeEachInner"); } @Test void innerTest1() { record("innerTest1"); } @AfterEach void afterEachInner() { record("afterEachInner"); } } } static class PreConstructOnMethod extends CallSequenceRecordingTestCase { PreConstructOnMethod() { record("constructor"); } @BeforeEach void beforeEach() { record("beforeEach"); } @ExtendWith(InstancePreConstructCallbackRecordingFoo.class) @Test void test1() { record("test1"); } @Test void test2() { record("test2"); } @AfterEach void afterEach() { record("afterEach"); } } @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(InstancePreConstructCallbackRecordingFoo.class) @ExtendWith(InstancePreConstructCallbackRecordingBar.class) static class PreConstructWithClassLifecycle extends CallSequenceRecordingTestCase { PreConstructWithClassLifecycle() { record("constructor"); } @BeforeEach void beforeEach() { record("beforeEach"); } @Test void test1() { callSequence.add("test1"); } @Test void test2() { callSequence.add("test2"); } } static abstract class AbstractTestInstancePreConstructCallback implements TestInstancePreConstructCallback { private final String name; AbstractTestInstancePreConstructCallback(String name) { this.name = name; } @Override public void preConstructTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext context) { assertThat(context.getTestInstance()).isNotPresent(); assertThat(context.getTestClass()).isPresent(); assertThat(factoryContext.getTestClass()).isSameAs(context.getTestClass().get()); callSequence.add( "PreConstructCallback: name=" + name + ", testClass=" + factoryContext.getTestClass().getSimpleName() + ", outerInstance: " + factoryContext.getOuterInstance().orElse(null)); } } static class InstancePreConstructCallbackRecordingFoo extends AbstractTestInstancePreConstructCallback { InstancePreConstructCallbackRecordingFoo() { super("foo"); } } static class InstancePreConstructCallbackRecordingBar extends AbstractTestInstancePreConstructCallback { InstancePreConstructCallbackRecordingBar() { super("bar"); } } static class InstancePreConstructCallbackRecordingBaz extends AbstractTestInstancePreConstructCallback { InstancePreConstructCallbackRecordingBaz() { super("baz"); } } } TestInstancePreDestroyCallbackTests.java000066400000000000000000000130441455764576500405300ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; /** * Integration tests that verify support for {@link TestInstancePreDestroyCallback}. * * @since 5.6 */ class TestInstancePreDestroyCallbackTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); @BeforeEach void resetCallSequence() { callSequence.clear(); } @Test void instancePreDestroyCallbacksInNestedClasses() { executeTestsForClass(OuterTestCase.class).testEvents().assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( // OuterTestCase "beforeOuterMethod", "testOuter", "fooPreDestroyCallbackTestInstance:OuterTestCase", // InnerTestCase "beforeOuterMethod", "beforeInnerMethod", "testInner", "bazPreDestroyCallbackTestInstance:InnerTestCase", "barPreDestroyCallbackTestInstance:InnerTestCase", "fooPreDestroyCallbackTestInstance:InnerTestCase" ); // @formatter:on } @Test void testSpecificTestInstancePreDestroyCallbackIsCalled() { executeTestsForClass(TestCaseWithTestSpecificTestInstancePreDestroyCallback.class).testEvents()// .assertStatistics(stats -> stats.started(1).succeeded(1)); // @formatter:off assertThat(callSequence).containsExactly( "beforeEachMethod", "test", "fooPreDestroyCallbackTestInstance:TestCaseWithTestSpecificTestInstancePreDestroyCallback" ); // @formatter:on } @Test void classLifecyclePreDestroyCallbacks() { executeTestsForClass(PerClassLifecyclePreDestroyCallbacksWithTwoTestMethods.class).testEvents()// .assertStatistics(stats -> stats.started(2).succeeded(2)); // @formatter:off assertThat(callSequence).containsExactly( "beforeEachMethod", "test1", "beforeEachMethod", "test2", "barPreDestroyCallbackTestInstance:PerClassLifecyclePreDestroyCallbacksWithTwoTestMethods", "fooPreDestroyCallbackTestInstance:PerClassLifecyclePreDestroyCallbacksWithTwoTestMethods" ); // @formatter:on } // ------------------------------------------------------------------- private abstract static class Destroyable { boolean destroyed; void setDestroyed() { this.destroyed = true; } } @ExtendWith(FooInstancePreDestroyCallback.class) static class OuterTestCase extends Destroyable { @BeforeEach void beforeOuterMethod() { callSequence.add("beforeOuterMethod"); } @Test void testOuter() { assertFalse(destroyed); callSequence.add("testOuter"); } @Nested @ExtendWith(BarInstancePreDestroyCallback.class) @ExtendWith(BazInstancePreDestroyCallback.class) class InnerTestCase extends Destroyable { @BeforeEach void beforeInnerMethod() { assertFalse(destroyed); callSequence.add("beforeInnerMethod"); } @Test void testInner() { callSequence.add("testInner"); } } } static class TestCaseWithTestSpecificTestInstancePreDestroyCallback extends Destroyable { @BeforeEach void beforeEachMethod() { assertFalse(destroyed); callSequence.add("beforeEachMethod"); } @ExtendWith(FooInstancePreDestroyCallback.class) @Test void test() { callSequence.add("test"); } } @TestInstance(PER_CLASS) @ExtendWith(FooInstancePreDestroyCallback.class) @ExtendWith(BarInstancePreDestroyCallback.class) static class PerClassLifecyclePreDestroyCallbacksWithTwoTestMethods extends Destroyable { @BeforeEach void beforeEachMethod() { callSequence.add("beforeEachMethod"); } @Test void test1() { callSequence.add("test1"); } @Test void test2() { callSequence.add("test2"); } } static abstract class AbstractTestInstancePreDestroyCallback implements TestInstancePreDestroyCallback { private final String name; AbstractTestInstancePreDestroyCallback(String name) { this.name = name; } @Override public void preDestroyTestInstance(ExtensionContext context) { assertThat(context.getTestInstance()).isPresent(); Object testInstance = context.getTestInstance().get(); if (testInstance instanceof Destroyable) { ((Destroyable) testInstance).setDestroyed(); } callSequence.add(name + "PreDestroyCallbackTestInstance:" + testInstance.getClass().getSimpleName()); } } static class FooInstancePreDestroyCallback extends AbstractTestInstancePreDestroyCallback { FooInstancePreDestroyCallback() { super("foo"); } } static class BarInstancePreDestroyCallback extends AbstractTestInstancePreDestroyCallback { BarInstancePreDestroyCallback() { super("bar"); } } static class BazInstancePreDestroyCallback extends AbstractTestInstancePreDestroyCallback { BazInstancePreDestroyCallback() { super("baz"); } } } TestInstancePreDestroyCallbackUtilityMethodTests.java000066400000000000000000000070241455764576500432560ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.reportEntry; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; public class TestInstancePreDestroyCallbackUtilityMethodTests extends AbstractJupiterTestEngineTests { @TestFactory Stream destroysWhatWasPostProcessed() { var testClasses = Stream.of(PerMethodLifecycleOnAllLevels.class, PerMethodWithinPerClassLifecycle.class, PerClassWithinPerMethodLifecycle.class, PerClassLifecycleOnAllLevels.class); return testClasses.map(testClass -> dynamicTest( // testClass.getSimpleName(), // () -> executeTestsForClass(testClass).allEvents().debug() // .assertStatistics(stats -> stats.reportingEntryPublished(4)) // .assertEventsMatchLooselyInOrder( // reportEntry(Map.of("post-process", testClass.getSimpleName())), reportEntry(Map.of("post-process", "Inner")), // event(test(), started()), // reportEntry(Map.of("pre-destroy", "Inner")), // reportEntry(Map.of("pre-destroy", testClass.getSimpleName())) // ))); } @ExtendWith(TestInstanceLifecycleExtension.class) static class PerMethodLifecycleOnAllLevels { @Nested class Inner { @Test void test() { } } } @ExtendWith(TestInstanceLifecycleExtension.class) @TestInstance(PER_CLASS) static class PerMethodWithinPerClassLifecycle { @Nested class Inner { @Test void test() { } } } @ExtendWith(TestInstanceLifecycleExtension.class) static class PerClassWithinPerMethodLifecycle { @Nested @TestInstance(PER_CLASS) class Inner { @Test void test() { } } } @ExtendWith(TestInstanceLifecycleExtension.class) @TestInstance(PER_CLASS) static class PerClassLifecycleOnAllLevels { @Nested @TestInstance(PER_CLASS) class Inner { @Test void test() { } } } private static class TestInstanceLifecycleExtension implements TestInstancePostProcessor, TestInstancePreDestroyCallback { @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { context.publishReportEntry("post-process", testInstance.getClass().getSimpleName()); } @Override public void preDestroyTestInstance(ExtensionContext context) { TestInstancePreDestroyCallback.preDestroyTestInstances(context, testInstance -> context.publishReportEntry("pre-destroy", testInstance.getClass().getSimpleName())); } } } TestReporterParameterResolverTests.java000066400000000000000000000043661455764576500405220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ class TestReporterParameterResolverTests { TestReporterParameterResolver resolver = new TestReporterParameterResolver(); @Test void supports() { Parameter parameter1 = findParameterOfMethod("methodWithTestReporterParameter", TestReporter.class); assertTrue(this.resolver.supportsParameter(parameterContext(parameter1), null)); Parameter parameter2 = findParameterOfMethod("methodWithoutTestReporterParameter", String.class); assertFalse(this.resolver.supportsParameter(parameterContext(parameter2), null)); } @Test void resolve() { Parameter parameter = findParameterOfMethod("methodWithTestReporterParameter", TestReporter.class); TestReporter testReporter = this.resolver.resolveParameter(parameterContext(parameter), mock()); assertNotNull(testReporter); } private Parameter findParameterOfMethod(String methodName, Class... parameterTypes) { Method method = ReflectionUtils.findMethod(Sample.class, methodName, parameterTypes).get(); return method.getParameters()[0]; } private static ParameterContext parameterContext(Parameter parameter) { ParameterContext parameterContext = mock(); when(parameterContext.getParameter()).thenReturn(parameter); return parameterContext; } static class Sample { void methodWithTestReporterParameter(TestReporter reporter) { } void methodWithoutTestReporterParameter(String nothing) { } } } TestWatcherTests.java000066400000000000000000000313611455764576500347250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.function.Predicate.not; import static java.util.stream.Collectors.toUnmodifiableList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestWatcher; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.testkit.engine.EngineExecutionResults; /** * Integration tests for the {@link TestWatcher} extension API. * * @since 5.4 */ class TestWatcherTests extends AbstractJupiterTestEngineTests { private static final List testWatcherMethodNames = Arrays.stream(TestWatcher.class.getDeclaredMethods())// .filter(not(Method::isSynthetic))// .map(Method::getName)// .collect(toUnmodifiableList()); @BeforeEach void clearResults() { TrackingTestWatcher.results.clear(); } @Test void testWatcherIsInvokedForTestMethodsInTopLevelAndNestedTestClasses() { assertCommonStatistics(executeTestsForClass(TrackingTestWatcherTestMethodsTestCase.class)); assertThat(TrackingTestWatcher.results.keySet()).containsAll(testWatcherMethodNames); TrackingTestWatcher.results.values().forEach(testMethodNames -> assertEquals(2, testMethodNames.size())); } @Test void testWatcherIsInvokedForRepeatedTestMethods() { EngineExecutionResults results = executeTestsForClass(TrackingTestWatcherRepeatedTestMethodsTestCase.class); results.containerEvents().assertStatistics( stats -> stats.skipped(1).started(5).succeeded(5).aborted(0).failed(0)); results.testEvents().assertStatistics( stats -> stats.dynamicallyRegistered(6).skipped(0).started(6).succeeded(2).aborted(2).failed(2)); // Since the @RepeatedTest container is disabled, the individual invocations never occur. assertThat(TrackingTestWatcher.results.keySet()).containsAll(testWatcherMethodNames); // 2 => number of iterations declared in @RepeatedTest(2). TrackingTestWatcher.results.forEach((testWatcherMethod, testMethodNames) -> assertEquals( "testDisabled".equals(testWatcherMethod) ? 1 : 2, testMethodNames.size())); } @Test void testWatcherIsNotInvokedForTestFactoryMethods() { EngineExecutionResults results = executeTestsForClass(TrackingTestWatcherTestFactoryMethodsTestCase.class); results.containerEvents().assertStatistics( stats -> stats.skipped(1).started(5).succeeded(5).aborted(0).failed(0)); results.testEvents().assertStatistics( stats -> stats.dynamicallyRegistered(6).skipped(0).started(6).succeeded(2).aborted(2).failed(2)); // There should be zero results, since the TestWatcher API is not supported for @TestFactory containers. assertThat(TrackingTestWatcher.results).isEmpty(); } @Test @TrackLogRecords void testWatcherExceptionsAreLoggedAndSwallowed(LogRecordListener logRecordListener) { assertCommonStatistics(executeTestsForClass(ExceptionThrowingTestWatcherTestCase.class)); // @formatter:off long exceptionCount = logRecordListener.stream(MethodBasedTestDescriptor.class, Level.WARNING) .map(LogRecord::getThrown) .filter(JUnitException.class::isInstance) .map(throwable -> throwable.getStackTrace()[0].getMethodName()) .filter(testWatcherMethodNames::contains) .count(); // @formatter:on assertEquals(8, exceptionCount, "Thrown exceptions were not logged properly."); } @Test void testWatcherIsInvokedForTestMethodsInTestCaseWithProblematicConstructor() { EngineExecutionResults results = executeTestsForClass(ProblematicConstructorTestCase.class); results.testEvents().assertStatistics(stats -> stats.skipped(0).started(8).succeeded(0).aborted(0).failed(8)); assertThat(TrackingTestWatcher.results.keySet()).containsExactly("testFailed"); assertThat(TrackingTestWatcher.results.get("testFailed")).hasSize(8); } @Test void testWatcherSemanticsWhenRegisteredAtClassLevel() { Class testClass = ClassLevelTestWatcherTestCase.class; assertStatsForAbstractDisabledMethodsTestCase(testClass); // We get "testDisabled" events for the @Test method and the @RepeatedTest container. assertThat(TrackingTestWatcher.results.get("testDisabled")).containsExactly("test", "repeatedTest"); } @Test void testWatcherSemanticsWhenRegisteredAtInstanceLevelWithTestInstanceLifecyclePerClass() { Class testClass = TestInstancePerClassInstanceLevelTestWatcherTestCase.class; assertStatsForAbstractDisabledMethodsTestCase(testClass); // We get "testDisabled" events for the @Test method and the @RepeatedTest container. assertThat(TrackingTestWatcher.results.get("testDisabled")).containsExactly("test", "repeatedTest"); } @Test void testWatcherSemanticsWhenRegisteredAtInstanceLevelWithTestInstanceLifecyclePerMethod() { Class testClass = TestInstancePerMethodInstanceLevelTestWatcherTestCase.class; assertStatsForAbstractDisabledMethodsTestCase(testClass); // Since the TestWatcher is registered at the instance level with test instance // lifecycle per-method semantics, we get a "testDisabled" event only for the @Test // method and NOT for the @RepeatedTest container. assertThat(TrackingTestWatcher.results.get("testDisabled")).containsExactly("test"); } @Test void testWatcherSemanticsWhenRegisteredAtMethodLevel() { Class testClass = MethodLevelTestWatcherTestCase.class; assertStatsForAbstractDisabledMethodsTestCase(testClass); // We get "testDisabled" events for the @Test method and the @RepeatedTest container. assertThat(TrackingTestWatcher.results.get("testDisabled")).containsExactly("test", "repeatedTest"); } private void assertCommonStatistics(EngineExecutionResults results) { results.containerEvents().assertStatistics(stats -> stats.started(3).succeeded(3).failed(0)); results.testEvents().assertStatistics(stats -> stats.skipped(2).started(6).succeeded(2).aborted(2).failed(2)); } private void assertStatsForAbstractDisabledMethodsTestCase(Class testClass) { EngineExecutionResults results = executeTestsForClass(testClass); results.containerEvents().assertStatistics(// stats -> stats.skipped(1).started(2).succeeded(2).aborted(0).failed(0)); results.testEvents().assertStatistics(// stats -> stats.skipped(1).started(0).succeeded(0).aborted(0).failed(0)); assertThat(TrackingTestWatcher.results.keySet()).containsExactly("testDisabled"); } // ------------------------------------------------------------------------- private static abstract class AbstractTestCase { @Test public void successfulTest() { //no-op } @Test public void failedTest() { fail("Must fail"); } @Test public void abortedTest() { assumeTrue(false); } @Test @Disabled public void skippedTest() { //no-op } @Nested class SecondLevel { @Test public void successfulTest() { //no-op } @Test public void failedTest() { fail("Must fail"); } @Test public void abortedTest() { assumeTrue(false); } @Test @Disabled public void skippedTest() { //no-op } } } @ExtendWith(TrackingTestWatcher.class) static class TrackingTestWatcherTestMethodsTestCase extends AbstractTestCase { } @ExtendWith(TrackingTestWatcher.class) static class TrackingTestWatcherRepeatedTestMethodsTestCase { @RepeatedTest(2) void successfulTest() { //no-op } @RepeatedTest(2) void failedTest() { fail("Must fail"); } @RepeatedTest(2) void abortedTest() { assumeTrue(false); } @RepeatedTest(2) @Disabled void skippedTest() { //no-op } } @ExtendWith(TrackingTestWatcher.class) static class TrackingTestWatcherTestFactoryMethodsTestCase { @TestFactory Stream successfulTest() { return Stream.of("A", "B").map(text -> dynamicTest(text, () -> assertTrue(true))); } @TestFactory Stream failedTest() { return Stream.of("A", "B").map(text -> dynamicTest(text, () -> fail("Must fail"))); } @TestFactory Stream abortedTest() { return Stream.of("A", "B").map(text -> dynamicTest(text, () -> assumeTrue(false))); } @TestFactory @Disabled Stream skippedTest() { return Stream.of("A", "B").map(text -> dynamicTest(text, () -> assertTrue(false))); } } @ExtendWith(ExceptionThrowingTestWatcher.class) static class ExceptionThrowingTestWatcherTestCase extends AbstractTestCase { } @ExtendWith(TrackingTestWatcher.class) static class ProblematicConstructorTestCase extends AbstractTestCase { ProblematicConstructorTestCase(Object ignore) { } } @TestMethodOrder(OrderAnnotation.class) private static abstract class AbstractDisabledMethodsTestCase { @Disabled @Test @Order(1) void test() { } @Disabled @RepeatedTest(2) @Order(2) void repeatedTest() { } } static class ClassLevelTestWatcherTestCase extends AbstractDisabledMethodsTestCase { @RegisterExtension static TestWatcher watcher = new TrackingTestWatcher(); } @TestInstance(Lifecycle.PER_CLASS) static class TestInstancePerClassInstanceLevelTestWatcherTestCase extends AbstractDisabledMethodsTestCase { @RegisterExtension TestWatcher watcher = new TrackingTestWatcher(); } @TestInstance(Lifecycle.PER_METHOD) static class TestInstancePerMethodInstanceLevelTestWatcherTestCase extends AbstractDisabledMethodsTestCase { @RegisterExtension TestWatcher watcher = new TrackingTestWatcher(); } static class MethodLevelTestWatcherTestCase extends AbstractDisabledMethodsTestCase { @Override @Disabled @Test @Order(1) @ExtendWith(TrackingTestWatcher.class) void test() { } @Override @Disabled @RepeatedTest(1) @Order(2) @ExtendWith(TrackingTestWatcher.class) void repeatedTest() { } } private static class TrackingTestWatcher implements TestWatcher { private static final Map> results = new HashMap<>(); @Override public void testSuccessful(ExtensionContext context) { trackResult("testSuccessful", context); } @Override public void testAborted(ExtensionContext context, Throwable cause) { trackResult("testAborted", context); } @Override public void testFailed(ExtensionContext context, Throwable cause) { trackResult("testFailed", context); } @Override public void testDisabled(ExtensionContext context, Optional reason) { trackResult("testDisabled", context); } protected void trackResult(String testWatcherMethod, ExtensionContext context) { String testMethod = context.getRequiredTestMethod().getName(); results.computeIfAbsent(testWatcherMethod, k -> new ArrayList<>()).add(testMethod); } } private static class ExceptionThrowingTestWatcher implements TestWatcher { @Override public void testSuccessful(ExtensionContext context) { throw new JUnitException("Exception in testSuccessful()"); } @Override public void testDisabled(ExtensionContext context, Optional reason) { throw new JUnitException("Exception in testDisabled()"); } @Override public void testAborted(ExtensionContext context, Throwable cause) { throw new JUnitException("Exception in testAborted()"); } @Override public void testFailed(ExtensionContext context, Throwable cause) { throw new JUnitException("Exception in testFailed()"); } } } TimeoutConfigurationTests.java000066400000000000000000000205401455764576500366430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Timeout.ThreadMode.SEPARATE_THREAD; import static org.junit.jupiter.engine.Constants.DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Optional; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; /** * @since 5.5 */ class TimeoutConfigurationTests { ExtensionContext extensionContext = mock(); TimeoutConfiguration config = new TimeoutConfiguration(extensionContext); @Test void noTimeoutIfNoPropertiesAreSet() { assertThat(config.getDefaultBeforeAllMethodTimeout()).isEmpty(); assertThat(config.getDefaultBeforeEachMethodTimeout()).isEmpty(); assertThat(config.getDefaultTestMethodTimeout()).isEmpty(); assertThat(config.getDefaultTestTemplateMethodTimeout()).isEmpty(); assertThat(config.getDefaultTestFactoryMethodTimeout()).isEmpty(); assertThat(config.getDefaultAfterEachMethodTimeout()).isEmpty(); assertThat(config.getDefaultAfterAllMethodTimeout()).isEmpty(); assertThat(config.getDefaultTimeoutThreadMode()).isEmpty(); } @Test void defaultTimeoutIsUsedUnlessAMoreSpecificOneIsSet() { when(extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_PROPERTY_NAME)).thenReturn(Optional.of("42")); assertThat(config.getDefaultBeforeAllMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultBeforeEachMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultTestMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultTestTemplateMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultTestFactoryMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultAfterEachMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); assertThat(config.getDefaultAfterAllMethodTimeout()).contains(new TimeoutDuration(42, SECONDS)); } @Test void defaultCategoryTimeoutIsUsedUnlessAMoreSpecificOneIsSet() { when(extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_PROPERTY_NAME)).thenReturn(Optional.of("2")); when(extensionContext.getConfigurationParameter(DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("3")); when(extensionContext.getConfigurationParameter(DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("5")); assertThat(config.getDefaultBeforeAllMethodTimeout()).contains(new TimeoutDuration(3, SECONDS)); assertThat(config.getDefaultBeforeEachMethodTimeout()).contains(new TimeoutDuration(3, SECONDS)); assertThat(config.getDefaultTestMethodTimeout()).contains(new TimeoutDuration(5, SECONDS)); assertThat(config.getDefaultTestTemplateMethodTimeout()).contains(new TimeoutDuration(5, SECONDS)); assertThat(config.getDefaultTestFactoryMethodTimeout()).contains(new TimeoutDuration(5, SECONDS)); assertThat(config.getDefaultAfterEachMethodTimeout()).contains(new TimeoutDuration(3, SECONDS)); assertThat(config.getDefaultAfterAllMethodTimeout()).contains(new TimeoutDuration(3, SECONDS)); } @Test void specificTimeoutsAreUsedIfSet() { when(extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_PROPERTY_NAME)).thenReturn(Optional.of("2")); when(extensionContext.getConfigurationParameter(DEFAULT_LIFECYCLE_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("3")); when(extensionContext.getConfigurationParameter(DEFAULT_TESTABLE_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("5")); when(extensionContext.getConfigurationParameter(DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("7ns")); when(extensionContext.getConfigurationParameter(DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("11μs")); when(extensionContext.getConfigurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("13ms")); when(extensionContext.getConfigurationParameter(DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("17s")); when(extensionContext.getConfigurationParameter(DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("19m")); when(extensionContext.getConfigurationParameter(DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("23h")); when(extensionContext.getConfigurationParameter(DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("29d")); assertThat(config.getDefaultBeforeAllMethodTimeout()).contains(new TimeoutDuration(7, NANOSECONDS)); assertThat(config.getDefaultBeforeEachMethodTimeout()).contains(new TimeoutDuration(11, MICROSECONDS)); assertThat(config.getDefaultTestMethodTimeout()).contains(new TimeoutDuration(13, MILLISECONDS)); assertThat(config.getDefaultTestTemplateMethodTimeout()).contains(new TimeoutDuration(17, SECONDS)); assertThat(config.getDefaultTestFactoryMethodTimeout()).contains(new TimeoutDuration(19, MINUTES)); assertThat(config.getDefaultAfterEachMethodTimeout()).contains(new TimeoutDuration(23, HOURS)); assertThat(config.getDefaultAfterAllMethodTimeout()).contains(new TimeoutDuration(29, DAYS)); } @Test @TrackLogRecords void logsInvalidValues(LogRecordListener logRecordListener) { when(extensionContext.getConfigurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME)).thenReturn( Optional.of("invalid")); assertThat(config.getDefaultTestMethodTimeout()).isEmpty(); assertThat(logRecordListener.stream(Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Ignored invalid timeout 'invalid' set via the 'junit.jupiter.execution.timeout.test.method.default' configuration parameter."); } @Test void specificThreadModeIsUsed() { when(extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)).thenReturn( Optional.of("SEPARATE_THREAD")); assertThat(config.getDefaultTimeoutThreadMode()).contains(SEPARATE_THREAD); } @Test @TrackLogRecords void logsInvalidThreadModeValueAndReturnEmpty(LogRecordListener logRecordListener) { when(extensionContext.getConfigurationParameter(DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)).thenReturn( Optional.of("invalid")); assertThat(config.getDefaultTimeoutThreadMode()).isNotPresent(); assertThat(logRecordListener.stream(Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Invalid timeout thread mode 'invalid' set via the 'junit.jupiter.execution.timeout.thread.mode.default' configuration parameter."); } } TimeoutDurationParserTests.java000066400000000000000000000047651455764576500370110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.time.format.DateTimeParseException; import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; /** * @since 5.5 */ class TimeoutDurationParserTests { private final TimeoutDurationParser parser = new TimeoutDurationParser(); @Test void parsesNumberWithoutUnitIntoSecondsDurations() { assertEquals(new TimeoutDuration(42, SECONDS), parser.parse("42")); } @TestFactory Stream parsesNumbersWithUnits() { var unitsWithRepresentations = Map.of( // NANOSECONDS, "ns", // MICROSECONDS, "μs", // MILLISECONDS, "ms", // SECONDS, "s", // MINUTES, "m", // HOURS, "h", // DAYS, "d"); return unitsWithRepresentations.entrySet().stream() // .map(entry -> { var unit = entry.getKey(); var plainRepresentation = entry.getValue(); var representations = Stream.of( // plainRepresentation, // " " + plainRepresentation, // plainRepresentation.toUpperCase(), // " " + plainRepresentation.toUpperCase()); return dynamicContainer(unit.name().toLowerCase(), representations.map(representation -> dynamicTest("\"" + representation + "\"", () -> { var expected = new TimeoutDuration(42, unit); var actual = parser.parse("42" + representation); assertEquals(expected, actual); }))); }); } @Test void rejectsNumbersStartingWithZero() { assertThrows(DateTimeParseException.class, () -> parser.parse("01")); } } TimeoutDurationTests.java000066400000000000000000000022701455764576500356210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; /** * @since 5.5 */ class TimeoutDurationTests { @Test void formatsDurationNicely() { assertThat(new TimeoutDuration(1, SECONDS)).hasToString("1 second"); assertThat(new TimeoutDuration(2, SECONDS)).hasToString("2 seconds"); } @Test void fulfillsEqualsAndHashCodeContract() { var oneSecond = new TimeoutDuration(1, SECONDS); assertThat(oneSecond) // .isEqualTo(oneSecond) // .isEqualTo(new TimeoutDuration(1, SECONDS)) // .hasSameHashCodeAs(new TimeoutDuration(1, SECONDS)) // .isNotEqualTo("foo") // .isNotEqualTo(new TimeoutDuration(2, SECONDS)) // .isNotEqualTo(new TimeoutDuration(1, MINUTES)); } } TimeoutExceptionFactoryTests.java000066400000000000000000000045151455764576500373260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.engine.extension.TimeoutExceptionFactory.create; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; /** * @since 5.9 */ @DisplayName("TimeoutExceptionFactory") class TimeoutExceptionFactoryTests { private static final TimeoutDuration tenMillisDuration = new TimeoutDuration(10, MILLISECONDS); private static final Exception suppressedException = new Exception("Winke!"); private static final String methodSignature = "test()"; @Test @DisplayName("creates exception with method signature and timeout") void createExceptionWithMethodSignatureTimeout() { TimeoutException exception = create(methodSignature, tenMillisDuration); assertThat(exception) // .hasMessage("test() timed out after 10 milliseconds") // .hasNoSuppressedExceptions(); } @Test @DisplayName("creates exception with method signature, timeout and throwable") void createExceptionWithMethodSignatureTimeoutAndThrowable() { TimeoutException exception = create(methodSignature, tenMillisDuration, suppressedException); assertThat(exception) // .hasMessage("test() timed out after 10 milliseconds") // .hasSuppressedException(suppressedException); } @Nested @DisplayName("throws exception when") class ThrowException { @Test @DisplayName("method signature is null") void methodSignatureIsnull() { assertThatThrownBy(() -> create(null, tenMillisDuration, suppressedException)) // .hasMessage("method signature must not be null"); } @Test @DisplayName("method timeout duration is null") void timeoutDurationIsnull() { assertThatThrownBy(() -> create(methodSignature, null, suppressedException)) // .hasMessage("timeout duration must not be null"); } } } TimeoutExtensionTests.java000066400000000000000000000746501455764576500360230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.Timeout.ThreadMode.SAME_THREAD; import static org.junit.jupiter.api.Timeout.ThreadMode.SEPARATE_THREAD; import static org.junit.jupiter.engine.Constants.DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.TIMEOUT_MODE_PROPERTY_NAME; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.time.Duration; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.RuntimeUtils; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; import org.junit.platform.testkit.engine.Execution; import org.opentest4j.AssertionFailedError; /** * @since 5.5 */ @DisplayName("@Timeout") class TimeoutExtensionTests extends AbstractJupiterTestEngineTests { @Test @DisplayName("is applied on annotated @Test methods") void appliesTimeoutOnAnnotatedTestMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutAnnotatedTestMethodTestCase.class, "testMethod")) // .configurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testMethod() timed out after 10 milliseconds"); } @Test @DisplayName("is not applied on annotated @Test methods using timeout mode: disabled") void doesNotApplyTimeoutOnAnnotatedTestMethodsUsingDisabledTimeoutMode() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutAnnotatedTestMethodTestCase.class, "testMethod")) // .configurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .configurationParameter(TIMEOUT_MODE_PROPERTY_NAME, "disabled").build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable()) // .isEmpty(); } @Test @DisplayName("is not applied on annotated @Test methods using timeout mode: disabled") void applyTimeoutOnAnnotatedTestMethodsUsingDisabledOnDebugTimeoutMode() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutAnnotatedTestMethodTestCase.class, "testMethod")) // .configurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .configurationParameter(TIMEOUT_MODE_PROPERTY_NAME, "disabled_on_debug").build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // // The check to see if debugging is pushing the timer just above 1 second .isLessThan(Duration.ofSeconds(2)); // Should we test if we're debugging? This test will fail if we are debugging. if (RuntimeUtils.isDebugMode()) { assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable()) // .isEmpty(); } else { assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testMethod() timed out after 10 milliseconds"); } } @Test @DisplayName("is applied on annotated @TestTemplate methods") void appliesTimeoutOnAnnotatedTestTemplateMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutAnnotatedTestMethodTestCase.class, "testTemplateMethod")) // .configurationParameter(DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Stream.of("repetition 1", "repetition 2").forEach(displayName -> { Execution execution = findExecution(results.testEvents(), displayName); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testTemplateMethod() timed out after 10 milliseconds"); }); } @Test @DisplayName("is applied on annotated @TestFactory methods") void appliesTimeoutOnAnnotatedTestFactoryMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutAnnotatedTestMethodTestCase.class, "testFactoryMethod")) // .configurationParameter(DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.containerEvents(), "testFactoryMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testFactoryMethod() timed out after 10 milliseconds"); } @TestFactory @DisplayName("is applied on testable methods in annotated classes") Stream appliesTimeoutOnTestableMethodsInAnnotatedClasses() { return Stream.of(TimeoutAnnotatedClassTestCase.class, InheritedTimeoutAnnotatedClassTestCase.class).map( testClass -> dynamicTest(testClass.getSimpleName(), () -> { EngineExecutionResults results = executeTests(request() // .selectors(selectClass(testClass)) // .configurationParameter(DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .configurationParameter(DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .configurationParameter(DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Stream.of("testMethod()", "repetition 1", "repetition 2", "testFactoryMethod()").forEach( displayName -> { Execution execution = findExecution(results.allEvents(), displayName); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessageEndingWith("timed out after 10000000 nanoseconds"); }); })); } @Test @DisplayName("fails methods that do not throw InterruptedException") void failsMethodsWithoutInterruptedException() { EngineExecutionResults results = executeTestsForClass(MethodWithoutInterruptedExceptionTestCase.class); Execution execution = findExecution(results.testEvents(), "methodThatDoesNotThrowInterruptedException()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(1)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getStatus()).isEqualTo(FAILED); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("methodThatDoesNotThrowInterruptedException() timed out after 1 millisecond"); } @Test @DisplayName("is applied on annotated @BeforeAll methods") void appliesTimeoutOnAnnotatedBeforeAllMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectClass(TimeoutAnnotatedBeforeAllMethodTestCase.class)) // .configurationParameter(DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.containerEvents(), TimeoutAnnotatedBeforeAllMethodTestCase.class.getSimpleName()); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("setUp() timed out after 10 milliseconds"); } @Test @DisplayName("is applied on annotated @BeforeEach methods") void appliesTimeoutOnAnnotatedBeforeEachMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectClass(TimeoutAnnotatedBeforeEachMethodTestCase.class)) // .configurationParameter(DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("setUp() timed out after 10 milliseconds"); } @Test @DisplayName("is applied on annotated @AfterEach methods") void appliesTimeoutOnAnnotatedAfterEachMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectClass(TimeoutAnnotatedAfterEachMethodTestCase.class)) // .configurationParameter(DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("tearDown() timed out after 10 milliseconds"); } @Test @DisplayName("is applied on annotated @AfterAll methods") void appliesTimeoutOnAnnotatedAfterAllMethods() { EngineExecutionResults results = executeTests(request() // .selectors(selectClass(TimeoutAnnotatedAfterAllMethodTestCase.class)) // .configurationParameter(DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME, "42ns") // .build()); Execution execution = findExecution(results.containerEvents(), TimeoutAnnotatedAfterAllMethodTestCase.class.getSimpleName()); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("tearDown() timed out after 10 milliseconds"); } @TestFactory @DisplayName("is applied from configuration parameters by default") Stream appliesDefaultTimeoutsFromConfigurationParameters() { return Map.of(DEFAULT_BEFORE_ALL_METHOD_TIMEOUT_PROPERTY_NAME, "beforeAll()", // DEFAULT_BEFORE_EACH_METHOD_TIMEOUT_PROPERTY_NAME, "beforeEach()", // DEFAULT_TEST_METHOD_TIMEOUT_PROPERTY_NAME, "test()", // DEFAULT_TEST_TEMPLATE_METHOD_TIMEOUT_PROPERTY_NAME, "testTemplate()", // DEFAULT_TEST_FACTORY_METHOD_TIMEOUT_PROPERTY_NAME, "testFactory()", // DEFAULT_AFTER_EACH_METHOD_TIMEOUT_PROPERTY_NAME, "afterEach()", // DEFAULT_AFTER_ALL_METHOD_TIMEOUT_PROPERTY_NAME, "afterAll()" // ).entrySet().stream().map(entry -> dynamicTest("uses " + entry.getKey() + " config param", () -> { PlainTestCase.slowMethod = entry.getValue(); EngineExecutionResults results = executeTests(request() // .selectors(selectClass(PlainTestCase.class)) // .configurationParameter(entry.getKey(), "1ns") // .build()); var failure = results.allEvents().executions().failed() // .map(execution -> execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .findFirst(); assertThat(failure).containsInstanceOf(TimeoutException.class); assertThat(failure.get()).hasMessage(entry.getValue() + " timed out after 1 nanosecond"); })); } @Test @DisplayName("does not swallow unrecoverable exceptions") void doesNotSwallowUnrecoverableExceptions() { assertThrows(OutOfMemoryError.class, () -> executeTestsForClass(UnrecoverableExceptionTestCase.class)); } @Test @DisplayName("does not affect tests that don't exceed the timeout") void doesNotAffectTestsThatDoNotExceedTimeoutDuration() { executeTestsForClass(NonTimeoutExceedingTestCase.class).allEvents().assertStatistics(stats -> stats.failed(0)); } @Test @DisplayName("includes fully qualified class name if method is not in the test class") void includesClassNameIfMethodIsNotInTestClass() { EngineExecutionResults results = executeTestsForClass(NestedClassWithOuterSetupMethodTestCase.class); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getDuration()) // .isGreaterThanOrEqualTo(Duration.ofMillis(10)) // .isLessThan(Duration.ofSeconds(1)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessageEndingWith( "$NestedClassWithOuterSetupMethodTestCase#setUp() timed out after 10 milliseconds"); } @Test @DisplayName("reports illegal timeout durations") void reportsIllegalTimeoutDurations() { EngineExecutionResults results = executeTestsForClass(IllegalTimeoutDurationTestCase.class); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("timeout duration must be a positive number: 0"); } private Execution findExecution(Events events, String displayName) { return getOnlyElement(events // .executions() // .filter(execution -> execution.getTestDescriptor().getDisplayName().contains(displayName)) // .collect(toList())); } @Nested @DisplayName("separate thread") class SeparateThread { @Test @DisplayName("timeout exceeded") void timeoutExceededInSeparateThread() { EngineExecutionResults results = executeTestsForClass(TimeoutExceedingSeparateThreadTestCase.class); Execution execution = findExecution(results.testEvents(), "testMethod()"); Throwable failure = execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow(); assertThat(failure) // .isInstanceOf(TimeoutException.class) // .hasMessage("testMethod() timed out after 100 milliseconds"); assertThat(failure.getCause()) // .hasMessageStartingWith("Execution timed out in ") // .hasStackTraceContaining(TimeoutExceedingSeparateThreadTestCase.class.getName() + ".testMethod"); } @Test @DisplayName("non timeout exceeded") void nonTimeoutExceededInSeparateThread() { executeTestsForClass(NonTimeoutExceedingSeparateThreadTestCase.class).allEvents() // .assertStatistics(stats -> stats.failed(0)); } @Test @DisplayName("does not swallow unrecoverable exceptions") void separateThreadDoesNotSwallowUnrecoverableExceptions() { assertThrows(OutOfMemoryError.class, () -> executeTestsForClass(UnrecoverableExceptionInSeparateThreadTestCase.class)); } @Test @DisplayName("handles invocation exceptions") void separateThreadHandlesInvocationExceptions() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(ExceptionInSeparateThreadTestCase.class, "test")) // .build()); Execution execution = findExecution(results.testEvents(), "test()"); assertThat(execution.getDuration()) // .isLessThan(Duration.ofSeconds(5)); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(RuntimeException.class) // .hasMessage("Oppps!"); } @Test @DisplayName("propagates assertion exceptions") void separateThreadHandlesOpenTestFailedAssertion() { EngineExecutionResults results = executeTestsForClass(FailedAssertionInSeparateThreadTestCase.class); Execution openTestFailure = findExecution(results.testEvents(), "testOpenTestAssertion()"); assertThat(openTestFailure.getDuration()) // .isLessThan(Duration.ofSeconds(5)); assertThat(openTestFailure.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(AssertionFailedError.class); Execution javaLangFailure = findExecution(results.testEvents(), "testJavaLangAssertion()"); assertThat(javaLangFailure.getDuration()) // .isLessThan(Duration.ofSeconds(5)); assertThat(javaLangFailure.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(AssertionError.class); } @Test @DisplayName("when one test is stuck \"forever\" the next tests should not get stuck") void oneThreadStuckForever() { EngineExecutionResults results = executeTestsForClass(OneTestStuckForeverAndTheOthersNotTestCase.class); Execution stuckExecution = findExecution(results.testEvents(), "stuck()"); assertThat(stuckExecution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("stuck() timed out after 10 milliseconds"); Execution testZeroExecution = findExecution(results.testEvents(), "testZero()"); assertThat(testZeroExecution.getTerminationInfo().getExecutionResult().getStatus()) // .isEqualTo(Status.SUCCESSFUL); Execution testOneExecution = findExecution(results.testEvents(), "testOne()"); assertThat(testOneExecution.getTerminationInfo().getExecutionResult().getStatus()) // .isEqualTo(Status.SUCCESSFUL); } @Test @DisplayName("mixed same thread and separate thread tests") void mixedSameThreadAndSeparateThreadTests() { EngineExecutionResults results = executeTestsForClass(MixedSameThreadAndSeparateThreadTestCase.class); Execution stuck = findExecution(results.testEvents(), "testZero()"); assertThat(stuck.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testZero() timed out after 10 milliseconds"); Execution testZeroExecution = findExecution(results.testEvents(), "testOne()"); assertThat(testZeroExecution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testOne() timed out after 10 milliseconds"); Execution testOneExecution = findExecution(results.testEvents(), "testTwo()"); assertThat(testOneExecution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("testTwo() timed out after 10 milliseconds"); } @Test @DisplayName("one test is stuck \"forever\" in separate thread and other tests in same thread not") void oneThreadStuckForeverAndOtherTestsInSameThread() { EngineExecutionResults results = executeTestsForClass( OneTestStuckForeverAndTheOthersInSameThreadNotTestCase.class); Execution stuckExecution = findExecution(results.testEvents(), "stuck()"); assertThat(stuckExecution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("stuck() timed out after 10 milliseconds"); Execution testZeroExecution = findExecution(results.testEvents(), "testZero()"); assertThat(testZeroExecution.getTerminationInfo().getExecutionResult().getStatus()) // .isEqualTo(Status.SUCCESSFUL); Execution testOneExecution = findExecution(results.testEvents(), "testOne()"); assertThat(testOneExecution.getTerminationInfo().getExecutionResult().getStatus()) // .isEqualTo(Status.SUCCESSFUL); } @Test @DisplayName("is not applied on annotated @Test methods using timeout mode: disabled") void doesNotApplyTimeoutOnAnnotatedTestMethodsUsingDisabledTimeoutMode() { EngineExecutionResults results = executeTests(request() // .selectors(selectMethod(TimeoutExceedingSeparateThreadTestCase.class, "testMethod")) // .configurationParameter(TIMEOUT_MODE_PROPERTY_NAME, "disabled").build()); Execution execution = findExecution(results.testEvents(), "testMethod()"); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable()) // .isEmpty(); } @Nested @DisplayName("on class level") class OnClassLevel { @Test @DisplayName("timeout exceeded") void timeoutExceededInSeparateThreadOnClassLevel() { EngineExecutionResults results = executeTestsForClass(TimeoutExceededOnClassLevelTestCase.class); Execution execution = findExecution(results.testEvents(), "exceptionThrown()"); assertThat(execution.getTerminationInfo().getExecutionResult().getThrowable().orElseThrow()) // .isInstanceOf(TimeoutException.class) // .hasMessage("exceptionThrown() timed out after 100 milliseconds"); } @Test @DisplayName("non timeout exceeded") void nonTimeoutExceededInSeparateThreadOnClassLevel() { executeTestsForClass(NonTimeoutExceededOnClassLevelTestCase.class).allEvents() // .assertStatistics(stats -> stats.failed(0)); } } } static class TimeoutAnnotatedTestMethodTestCase { @Test @Timeout(value = 10, unit = MILLISECONDS) void testMethod() throws Exception { Thread.sleep(1000); } @RepeatedTest(2) @Timeout(value = 10, unit = MILLISECONDS) void testTemplateMethod() throws Exception { Thread.sleep(1000); } @TestFactory @Timeout(value = 10, unit = MILLISECONDS) Stream testFactoryMethod() throws Exception { Thread.sleep(1000); return Stream.empty(); } } static class TimeoutAnnotatedBeforeAllMethodTestCase { @BeforeAll @Timeout(value = 10, unit = MILLISECONDS) static void setUp() throws Exception { Thread.sleep(1000); } @Test void testMethod() { // never called } } static class TimeoutAnnotatedBeforeEachMethodTestCase { @BeforeEach @Timeout(value = 10, unit = MILLISECONDS) void setUp() throws Exception { Thread.sleep(1000); } @Test void testMethod() { // never called } } static class TimeoutAnnotatedAfterEachMethodTestCase { @Test void testMethod() { // do nothing } @AfterEach @Timeout(value = 10, unit = MILLISECONDS) void tearDown() throws Exception { Thread.sleep(1000); } } static class TimeoutAnnotatedAfterAllMethodTestCase { @Test void testMethod() { // do nothing } @AfterAll @Timeout(value = 10, unit = MILLISECONDS) static void tearDown() throws Exception { Thread.sleep(1000); } } @Timeout(value = 10_000_000, unit = NANOSECONDS) static class TimeoutAnnotatedClassTestCase { @Nested class NestedClass { @Test void testMethod() throws Exception { Thread.sleep(1000); } @RepeatedTest(2) void testTemplateMethod() throws Exception { Thread.sleep(1000); } @TestFactory Stream testFactoryMethod() throws Exception { Thread.sleep(1000); return Stream.empty(); } } } static class InheritedTimeoutAnnotatedClassTestCase extends TimeoutAnnotatedClassTestCase { } static class MethodWithoutInterruptedExceptionTestCase { @Test @Timeout(value = 1, unit = MILLISECONDS) void methodThatDoesNotThrowInterruptedException() { new EventuallyInterruptibleInvocation().proceed(); } } static class PlainTestCase { public static String slowMethod; @BeforeAll static void beforeAll() throws Exception { waitForInterrupt("beforeAll()"); } @BeforeEach void beforeEach() throws Exception { waitForInterrupt("beforeEach()"); } @Test void test() throws Exception { waitForInterrupt("test()"); } @RepeatedTest(2) void testTemplate() throws Exception { waitForInterrupt("testTemplate()"); } @TestFactory Stream testFactory() throws Exception { waitForInterrupt("testFactory()"); return Stream.empty(); } @AfterEach void afterEach() throws Exception { waitForInterrupt("afterEach()"); } @AfterAll static void afterAll() throws Exception { waitForInterrupt("afterAll()"); } private static void waitForInterrupt(String methodName) throws InterruptedException { if (methodName.equals(slowMethod)) { blockUntilInterrupted(); } } } static class UnrecoverableExceptionTestCase { @Test @Timeout(value = 1, unit = NANOSECONDS) void test() { new EventuallyInterruptibleInvocation().proceed(); throw new OutOfMemoryError(); } } @Timeout(10) static class NonTimeoutExceedingTestCase { @Test void testMethod() { } @RepeatedTest(1) void testTemplateMethod() { } @TestFactory Stream testFactoryMethod() { return Stream.of(dynamicTest("dynamicTest", () -> { })); } } static class NestedClassWithOuterSetupMethodTestCase { @Timeout(value = 10, unit = MILLISECONDS) @BeforeEach void setUp() throws Exception { Thread.sleep(1000); } @Nested class NestedClass { @BeforeEach void setUp() { } @Test void testMethod() { } } } static class IllegalTimeoutDurationTestCase { @Test @Timeout(0) void testMethod() { } } static class TimeoutExceedingWithInferredThreadModeTestCase { @Test @Timeout(value = 10, unit = MILLISECONDS) void testMethod() throws InterruptedException { Thread.sleep(1000); } } static class TimeoutExceedingSeparateThreadTestCase { @Test @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testMethod() throws InterruptedException { Thread.sleep(1000); } } static class NonTimeoutExceedingSeparateThreadTestCase { @Test @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testMethod() { } } static class UnrecoverableExceptionInSeparateThreadTestCase { @Test @Timeout(value = 100, unit = SECONDS, threadMode = SEPARATE_THREAD) void test() { throw new OutOfMemoryError(); } } static class ExceptionInSeparateThreadTestCase { @Test @Timeout(value = 5, unit = SECONDS, threadMode = SEPARATE_THREAD) void test() { throw new RuntimeException("Oppps!"); } } static class FailedAssertionInSeparateThreadTestCase { @Test @Timeout(value = 5, unit = SECONDS, threadMode = SEPARATE_THREAD) void testOpenTestAssertion() { throw new AssertionFailedError(); } @Test @Timeout(value = 5, unit = SECONDS, threadMode = SEPARATE_THREAD) void testJavaLangAssertion() { throw new AssertionError(); } } @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) static class TimeoutExceededOnClassLevelTestCase { @Test void exceptionThrown() throws InterruptedException { Thread.sleep(1000); } } @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) static class NonTimeoutExceededOnClassLevelTestCase { @Test void test() { } } @TestMethodOrder(OrderAnnotation.class) static class OneTestStuckForeverAndTheOthersNotTestCase { @Test @Order(0) @Timeout(value = 10, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void stuck() throws InterruptedException { blockUntilInterrupted(); } @Test @Order(1) @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testZero() { } @Test @Order(2) @Timeout(value = 100, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testOne() { } } static class MixedSameThreadAndSeparateThreadTestCase { @Test @Timeout(value = 10, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testZero() throws InterruptedException { Thread.sleep(1000); } @Test @Timeout(value = 10, unit = MILLISECONDS, threadMode = SAME_THREAD) void testOne() throws InterruptedException { Thread.sleep(1000); } @Test @Timeout(value = 10, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void testTwo() throws InterruptedException { Thread.sleep(1000); } } @TestMethodOrder(OrderAnnotation.class) static class OneTestStuckForeverAndTheOthersInSameThreadNotTestCase { @Test @Order(0) @Timeout(value = 10, unit = MILLISECONDS, threadMode = SEPARATE_THREAD) void stuck() throws InterruptedException { blockUntilInterrupted(); } @Test @Order(1) @Timeout(value = 10, unit = MILLISECONDS, threadMode = SAME_THREAD) void testZero() { } @Test @Order(2) @Timeout(value = 10, unit = MILLISECONDS, threadMode = SAME_THREAD) void testOne() { } } private static void blockUntilInterrupted() throws InterruptedException { new CountDownLatch(1).await(); } } TimeoutInvocationFactoryTests.java000066400000000000000000000071721455764576500375030ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.verify; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.engine.execution.NamespaceAwareStore; import org.junit.jupiter.engine.extension.TimeoutInvocationFactory.SingleThreadExecutorResource; import org.junit.jupiter.engine.extension.TimeoutInvocationFactory.TimeoutInvocationParameters; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; @DisplayName("TimeoutInvocationFactory") @ExtendWith(MockitoExtension.class) class TimeoutInvocationFactoryTests { @Spy private final Store store = new NamespaceAwareStore(new NamespacedHierarchicalStore<>(null), ExtensionContext.Namespace.create(TimeoutInvocationFactoryTests.class)); @Mock private Invocation invocation; @Mock private TimeoutDuration timeoutDuration; private TimeoutInvocationFactory timeoutInvocationFactory; private TimeoutInvocationParameters parameters; @BeforeEach void setUp() { parameters = new TimeoutInvocationParameters<>(invocation, timeoutDuration, () -> "description"); timeoutInvocationFactory = new TimeoutInvocationFactory(store); } @Test @DisplayName("throws exception when null store is provided on create") void shouldThrowExceptionWhenInstantiatingWithNullStore() { assertThatThrownBy(() -> new TimeoutInvocationFactory(null)) // .hasMessage("store must not be null"); } @Test @DisplayName("throws exception when null timeout thread mode is provided on create") void shouldThrowExceptionWhenNullTimeoutThreadModeIsProvidedWhenCreate() { assertThatThrownBy(() -> timeoutInvocationFactory.create(null, parameters)) // .hasMessage("thread mode must not be null"); } @Test @DisplayName("throws exception when null timeout invocation parameters is provided on create") void shouldThrowExceptionWhenNullTimeoutInvocationParametersIsProvidedWhenCreate() { assertThatThrownBy(() -> timeoutInvocationFactory.create(ThreadMode.SAME_THREAD, null)) // .hasMessage("timeout invocation parameters must not be null"); } @Test @DisplayName("creates timeout invocation for SAME_THREAD thread mode") void shouldCreateTimeoutInvocationForSameThreadTimeoutThreadMode() { var invocation = timeoutInvocationFactory.create(ThreadMode.SAME_THREAD, parameters); assertThat(invocation).isInstanceOf(SameThreadTimeoutInvocation.class); verify(store).getOrComputeIfAbsent(SingleThreadExecutorResource.class); } @Test @DisplayName("creates timeout invocation for SEPARATE_THREAD thread mode") void shouldCreateTimeoutInvocationForSeparateThreadTimeoutThreadMode() { var invocation = timeoutInvocationFactory.create(ThreadMode.SEPARATE_THREAD, parameters); assertThat(invocation).isInstanceOf(SeparateThreadTimeoutInvocation.class); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/sub/000077500000000000000000000000001455764576500314465ustar00rootroot00000000000000AlwaysDisabledCondition.java000066400000000000000000000022421455764576500367710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/sub/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension.sub; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; /** * Intentionally in a subpackage in order to properly test deactivation * of conditions based on patterns. In other words, we do not want this * condition declared in the same package as the * {@link org.junit.jupiter.engine.extension.DisabledCondition} * * ExecutionCondition always returns disabled, since we want to test the * deactivation of the condition itself. * * @since 5.7 */ public class AlwaysDisabledCondition implements ExecutionCondition { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return ConditionEvaluationResult.disabled("Always Disabled"); } } AnotherAlwaysDisabledCondition.java000066400000000000000000000015131455764576500403120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/sub/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension.sub; /** * Intentionally in a subpackage in order to properly test deactivation * of conditions based on patterns. In other words, we do not want this * condition declared in the same package as the * {@link org.junit.jupiter.engine.extension.DisabledCondition} * * ExecutionCondition always returns disabled, since we want to test the * deactivation of the condition itself. * * @since 5.7 */ public class AnotherAlwaysDisabledCondition extends AlwaysDisabledCondition { } SystemPropertyCondition.java000066400000000000000000000041451455764576500371360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/sub/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.extension.sub; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Objects; import java.util.Optional; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; /** * Intentionally in a subpackage in order to properly test deactivation * of conditions based on patterns. In other words, we do not want this * condition declared in the same package as the * {@link org.junit.jupiter.engine.extension.DisabledCondition} * * @since 5.0 */ public class SystemPropertyCondition implements ExecutionCondition { @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(SystemPropertyCondition.class) public @interface SystemProperty { String key(); String value(); } @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { Optional optional = findAnnotation(context.getElement(), SystemProperty.class); if (optional.isPresent()) { SystemProperty systemProperty = optional.get(); String key = systemProperty.key(); String expected = systemProperty.value(); String actual = System.getProperty(key); if (!Objects.equals(expected, actual)) { return ConditionEvaluationResult.disabled( String.format("System property [%s] has a value of [%s] instead of [%s]", key, actual, expected)); } } return ConditionEvaluationResult.enabled("@SystemProperty is not present"); } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/subpackage/000077500000000000000000000000001455764576500307465ustar00rootroot00000000000000SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase.java000066400000000000000000000012441455764576500472710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.subpackage; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * @since 5.9 */ public class SuperClassWithPackagePrivateLifecycleMethodInDifferentPackageTestCase { @BeforeEach void beforeEach() { fail(); } @Test void test() { } } junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/support/000077500000000000000000000000001455764576500303555ustar00rootroot00000000000000OpenTest4JAndJUnit4AwareThrowableCollectorTests.java000066400000000000000000000121371455764576500423070ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.support; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.net.URL; import java.net.URLClassLoader; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.internal.AssumptionViolatedException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link OpenTest4JAndJUnit4AwareThrowableCollector}. * * @since 5.5.2 */ @TrackLogRecords class OpenTest4JAndJUnit4AwareThrowableCollectorTests { @Test void simulateJUnit4NotInTheClasspath(LogRecordListener listener) throws Throwable { TestClassLoader classLoader = new TestClassLoader(true, false); doWithCustomClassLoader(classLoader, () -> { // Ensure that our custom ClassLoader actually throws a ClassNotFoundException // when attempting to load the AssumptionViolatedException class. assertThrows(ClassNotFoundException.class, () -> ReflectionUtils.tryToLoadClass(AssumptionViolatedException.class.getName()).get()); Class clazz = classLoader.loadClass(OpenTest4JAndJUnit4AwareThrowableCollector.class.getName()); assertNotNull(ReflectionUtils.newInstance(clazz)); // @formatter:off assertThat(listener.stream(Level.FINE).map(LogRecord::getMessage).findFirst().orElse("")) .isEqualTo( "Failed to load class org.junit.internal.AssumptionViolatedException: " + "only supporting org.opentest4j.TestAbortedException for aborted execution."); // @formatter:on }); } @Test void simulateHamcrestNotInTheClasspath(LogRecordListener listener) throws Throwable { TestClassLoader classLoader = new TestClassLoader(false, true); doWithCustomClassLoader(classLoader, () -> { // Ensure that our custom ClassLoader actually throws a NoClassDefFoundError // when attempting to load the AssumptionViolatedException class. assertThrows(NoClassDefFoundError.class, () -> ReflectionUtils.tryToLoadClass(AssumptionViolatedException.class.getName()).get()); Class clazz = classLoader.loadClass(OpenTest4JAndJUnit4AwareThrowableCollector.class.getName()); assertNotNull(ReflectionUtils.newInstance(clazz)); // @formatter:off assertThat(listener.stream(Level.FINE).map(LogRecord::getMessage).findFirst().orElse("")) .isEqualTo( "Failed to load class org.junit.internal.AssumptionViolatedException: " + "only supporting org.opentest4j.TestAbortedException for aborted execution. " + "Note that org.junit.internal.AssumptionViolatedException requires that Hamcrest is on the classpath."); // @formatter:on }); } private void doWithCustomClassLoader(ClassLoader classLoader, Executable executable) throws Throwable { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { // We have to set our custom ClassLoader as the TCCL so that // ReflectionUtils uses it (indirectly via ClassLoaderUtils). Thread.currentThread().setContextClassLoader(classLoader); executable.execute(); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } private static class TestClassLoader extends URLClassLoader { private static final URL[] CLASSPATH_URLS = new URL[] { OpenTest4JAndJUnit4AwareThrowableCollector.class.getProtectionDomain().getCodeSource().getLocation() }; private final boolean simulateJUnit4Missing; private final boolean simulateHamcrestMissing; public TestClassLoader(boolean simulateJUnit4Missing, boolean simulateHamcrestMissing) { super(CLASSPATH_URLS, getSystemClassLoader()); this.simulateJUnit4Missing = simulateJUnit4Missing; this.simulateHamcrestMissing = simulateHamcrestMissing; } @Override public Class loadClass(String name) throws ClassNotFoundException { // Load a new instance of the OpenTest4JAndJUnit4AwareThrowableCollector class if (name.equals(OpenTest4JAndJUnit4AwareThrowableCollector.class.getName())) { return findClass(name); } // Simulate that JUnit 4 is not in the classpath when loading AssumptionViolatedException if (this.simulateJUnit4Missing && name.equals(AssumptionViolatedException.class.getName())) { throw new ClassNotFoundException(AssumptionViolatedException.class.getName()); } // Simulate that Hamcrest is not in the classpath when loading AssumptionViolatedException if (this.simulateHamcrestMissing && name.equals(AssumptionViolatedException.class.getName())) { throw new NoClassDefFoundError("org/hamcrest/SelfDescribing"); } // Else return super.loadClass(name); } } } junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/000077500000000000000000000000001455764576500223515ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/000077500000000000000000000000001455764576500231405ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/000077500000000000000000000000001455764576500242715ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/000077500000000000000000000000001455764576500257535ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/api/000077500000000000000000000000001455764576500265245ustar00rootroot00000000000000KotlinAssertTimeoutAssertionsTests.kt000066400000000000000000000247141455764576500361040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals import org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.platform.commons.util.ExceptionUtils import org.opentest4j.AssertionFailedError import java.time.Duration.ofMillis import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicBoolean /** * Unit tests for JUnit Jupiter [Assertions]. * * @since 5.5 */ internal class KotlinAssertTimeoutAssertionsTests { // --- executable ---------------------------------------------------------- @Test fun assertTimeoutForExecutableThatCompletesBeforeTheTimeout() { changed.get().set(false) assertTimeout(ofMillis(500)) { changed.get().set(true) } assertTrue(changed.get().get(), "should have executed in the same thread") assertTimeout(ofMillis(500), "message") { } assertTimeout(ofMillis(500), "message") { } } @Test fun assertTimeoutForExecutableThatThrowsAnException() { val exception = assertThrows { assertTimeout(ofMillis(500)) { throw RuntimeException("not this time") } } assertMessageEquals(exception, "not this time") } @Test fun assertTimeoutForExecutableThatThrowsAnAssertionFailedError() { val exception = assertThrows { assertTimeout(ofMillis(500)) { fail("enigma") } } assertMessageEquals(exception, "enigma") } @Test fun assertTimeoutForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10)) { this.nap() } } assertMessageStartsWith(error, "execution exceeded timeout of 10 ms by") } @Test fun assertTimeoutWithMessageForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10), "Tempus Fugit") { this.nap() } } assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by") } @Test fun assertTimeoutWithMessageSupplierForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10), { "Tempus" + " " + "Fugit" }) { this.nap() } } assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by") } // --- supplier ------------------------------------------------------------ @Test fun assertTimeoutForSupplierThatCompletesBeforeTheTimeout() { changed.get().set(false) val result = assertTimeout(ofMillis(500)) { changed.get().set(true) "Tempus Fugit" } assertTrue(changed.get().get(), "should have executed in the same thread") assertEquals("Tempus Fugit", result) assertEquals("Tempus Fugit", assertTimeout(ofMillis(500), "message") { "Tempus Fugit" }) assertEquals("Tempus Fugit", assertTimeout(ofMillis(500), { "message" }, { "Tempus Fugit" })) } @Test fun assertTimeoutForSupplierThatThrowsAnException() { val exception = assertThrows { assertTimeout(ofMillis(500)) { ExceptionUtils.throwAsUncheckedException(RuntimeException("not this time")) } } assertMessageEquals(exception, "not this time") } @Test fun assertTimeoutForSupplierThatThrowsAnAssertionFailedError() { val exception = assertThrows { assertTimeout(ofMillis(500)) { fail("enigma") } } assertMessageEquals(exception, "enigma") } @Test fun assertTimeoutForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10)) { nap() } } assertMessageStartsWith(error, "execution exceeded timeout of 10 ms by") } @Test fun assertTimeoutWithMessageForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10), "Tempus Fugit") { nap() } } assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by") } @Test fun assertTimeoutWithMessageSupplierForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeout(ofMillis(10), { "Tempus" + " " + "Fugit" }) { nap() } } assertMessageStartsWith(error, "Tempus Fugit ==> execution exceeded timeout of 10 ms by") } // -- executable - preemptively --- @Test fun assertTimeoutPreemptivelyForExecutableThatCompletesBeforeTheTimeout() { changed.get().set(false) assertTimeoutPreemptively(ofMillis(500)) { changed.get().set(true) } assertFalse(changed.get().get(), "should have executed in a different thread") assertTimeoutPreemptively(ofMillis(500), "message") {} assertTimeoutPreemptively(ofMillis(500), { "message" }) {} } @Test fun assertTimeoutPreemptivelyForExecutableThatThrowsAnException() { val exception = assertThrows { assertTimeoutPreemptively(ofMillis(500)) { throw RuntimeException("not this time") } } assertMessageEquals(exception, "not this time") } @Test fun assertTimeoutPreemptivelyForExecutableThatThrowsAnAssertionFailedError() { val exception = assertThrows { assertTimeoutPreemptively(ofMillis(500)) { fail("enigma") } } assertMessageEquals(exception, "enigma") } @Test fun assertTimeoutPreemptivelyForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10)) { waitForInterrupt() } } assertMessageEquals(error, "execution timed out after 10 ms") } @Test fun assertTimeoutPreemptivelyWithMessageForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10), "Tempus Fugit") { waitForInterrupt() } } assertMessageEquals(error, "Tempus Fugit ==> execution timed out after 10 ms") } @Test fun assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10), { "Tempus" + " " + "Fugit" }) { waitForInterrupt() } } assertMessageEquals(error, "Tempus Fugit ==> execution timed out after 10 ms") } @Test fun assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesBeforeTheTimeout() { assertTimeoutPreemptively(ofMillis(500), { "Tempus" + " " + "Fugit" }) {} } // -- supplier - preemptively --- @Test fun assertTimeoutPreemptivelyForSupplierThatCompletesBeforeTheTimeout() { changed.get().set(false) val result = assertTimeoutPreemptively(ofMillis(500)) { changed.get().set(true) "Tempus Fugit" } assertFalse(changed.get().get(), "should have executed in a different thread") assertEquals("Tempus Fugit", result) assertEquals("Tempus Fugit", assertTimeoutPreemptively(ofMillis(500), "message") { "Tempus Fugit" }) assertEquals("Tempus Fugit", assertTimeoutPreemptively(ofMillis(500), { "message" }) { "Tempus Fugit" }) } @Test fun assertTimeoutPreemptivelyForSupplierThatThrowsAnException() { val exception = assertThrows { assertTimeoutPreemptively(ofMillis(500)) { ExceptionUtils.throwAsUncheckedException(RuntimeException("not this time")) } } assertMessageEquals(exception, "not this time") } @Test fun assertTimeoutPreemptivelyForSupplierThatThrowsAnAssertionFailedError() { val exception = assertThrows { assertTimeoutPreemptively(ofMillis(500)) { fail("enigma") } } assertMessageEquals(exception, "enigma") } @Test fun assertTimeoutPreemptivelyForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10)) { waitForInterrupt() } } assertMessageEquals(error, "execution timed out after 10 ms") } @Test fun assertTimeoutPreemptivelyWithMessageForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10), "Tempus Fugit") { waitForInterrupt() } } assertMessageEquals(error, "Tempus Fugit ==> execution timed out after 10 ms") } @Test fun assertTimeoutPreemptivelyWithMessageSupplierForSupplierThatCompletesAfterTheTimeout() { val error = assertThrows { assertTimeoutPreemptively(ofMillis(10), { "Tempus" + " " + "Fugit" }) { waitForInterrupt() } } assertMessageEquals(error, "Tempus Fugit ==> execution timed out after 10 ms") } /** * Take a nap for 100 milliseconds. */ private fun nap() { val start = System.currentTimeMillis() // workaround for imprecise clocks (yes, Windows, I'm talking about you) do { Thread.sleep(100) } while (System.currentTimeMillis() - start < 100) } private fun waitForInterrupt() { try { CountDownLatch(1).await() } catch (ignore: InterruptedException) { // ignore } } companion object { private val changed = ThreadLocal.withInitial { AtomicBoolean(false) } } } junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/api/KotlinAssertionsTests.kt000066400000000000000000000226251455764576500334310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals import org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith import org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.DynamicContainer.dynamicContainer import org.junit.jupiter.api.DynamicTest.dynamicTest import org.opentest4j.AssertionFailedError import org.opentest4j.MultipleFailuresError import java.util.stream.Stream import kotlin.reflect.KClass /** * Unit tests for JUnit Jupiter [org.junit.jupiter.api] top-level assertion functions. */ class KotlinAssertionsTests { // Bonus: no null check tests as these get handled by the compiler! @Test fun `assertAll with functions that do not throw exceptions`() { assertAll(Stream.of({ assertTrue(true) }, { assertFalse(false) })) assertAll("heading", Stream.of({ assertTrue(true) }, { assertFalse(false) })) assertAll(setOf({ assertTrue(true) }, { assertFalse(false) })) assertAll("heading", setOf({ assertTrue(true) }, { assertFalse(false) })) assertAll({ assertTrue(true) }, { assertFalse(false) }) assertAll("heading", { assertTrue(true) }, { assertFalse(false) }) } @Test fun `assertAll with functions that throw AssertionErrors`() { val multipleFailuresError = assertThrows { assertAll( { assertFalse(true) }, { assertFalse(true) } ) } assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError::class, AssertionFailedError::class) } @Test fun `assertThrows and fail`() { assertThrows { fail("message") } assertThrows { fail("message", AssertionError()) } assertThrows { fail("message", null) } assertThrows("should fail") { fail({ "message" }) } assertThrows({ "should fail" }) { fail(AssertionError()) } assertThrows({ "should fail" }) { fail(null as Throwable?) } } @Test fun `expected context exception testing`() = runBlocking { assertThrows("Should fail async") { suspend { fail("Should fail async") }() } } @TestFactory fun assertDoesNotThrow(): Stream = Stream.of( dynamicContainer( "succeeds when no exception thrown", Stream.of( dynamicTest("for no arguments variant") { val actual = assertDoesNotThrow { 1 } assertEquals(1, actual) }, dynamicTest("for no arguments variant (suspended)") { runBlocking { val actual = assertDoesNotThrow { suspend { 1 }() } assertEquals(1, actual) } }, dynamicTest("for message variant") { val actual = assertDoesNotThrow("message") { 2 } assertEquals(2, actual) }, dynamicTest("for message variant (suspended)") { runBlocking { val actual = assertDoesNotThrow("message") { suspend { 2 }() } assertEquals(2, actual) } }, dynamicTest("for message supplier variant") { val actual = assertDoesNotThrow({ "message" }) { 3 } assertEquals(3, actual) }, dynamicTest("for message supplier variant (suspended)") { runBlocking { val actual = assertDoesNotThrow({ "message" }) { suspend { 3 }() } assertEquals(3, actual) } } ) ), dynamicContainer( "fails when an exception is thrown", Stream.of( dynamicTest("for no arguments variant") { val exception = assertThrows { assertDoesNotThrow { fail("fail") } } assertMessageEquals( exception, "Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) }, dynamicTest("for no arguments variant (suspended)") { runBlocking { val exception = assertThrows { assertDoesNotThrow { suspend { fail("fail") }() } } assertMessageEquals( exception, "Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) } }, dynamicTest("for message variant") { val exception = assertThrows { assertDoesNotThrow("Does not throw") { fail("fail") } } assertMessageEquals( exception, "Does not throw ==> Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) }, dynamicTest("for message variant (suspended)") { runBlocking { val exception = assertThrows { assertDoesNotThrow("Does not throw") { suspend { fail("fail") }() } } assertMessageEquals( exception, "Does not throw ==> Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) } }, dynamicTest("for message supplier variant") { val exception = assertThrows { assertDoesNotThrow({ "Does not throw" }) { fail("fail") } } assertMessageEquals( exception, "Does not throw ==> Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) }, dynamicTest("for message supplier variant (suspended)") { runBlocking { val exception = assertThrows { assertDoesNotThrow({ "Does not throw" }) { suspend { fail("fail") }() } } assertMessageEquals( exception, "Does not throw ==> Unexpected exception thrown: org.opentest4j.AssertionFailedError: fail" ) } } ) ) ) @Test fun `assertAll with stream of functions that throw AssertionErrors`() { val multipleFailuresError = assertThrows("Should have thrown multiple errors") { assertAll(Stream.of({ assertFalse(true) }, { assertFalse(true) })) } assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError::class, AssertionFailedError::class) } @Test fun `assertAll with collection of functions that throw AssertionErrors`() { val multipleFailuresError = assertThrows("Should have thrown multiple errors") { assertAll(setOf({ assertFalse(true) }, { assertFalse(true) })) } assertExpectedExceptionTypes(multipleFailuresError, AssertionFailedError::class, AssertionFailedError::class) } @Test fun `assertThrows with function that does not throw an exception`() { val assertionMessage = "This will not throw an exception" val error = assertThrows("assertThrows did not throw the correct exception") { assertThrows(assertionMessage) { } // This should never execute: expectAssertionFailedError() } assertMessageStartsWith(error, assertionMessage) } companion object { fun assertExpectedExceptionTypes( multipleFailuresError: MultipleFailuresError, vararg exceptionTypes: KClass ) = AssertAllAssertionsTests.assertExpectedExceptionTypes( multipleFailuresError, *exceptionTypes.map { it.java }.toTypedArray() ) } } KotlinFailAssertionsTests.kt000066400000000000000000000072351455764576500341460ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api import org.junit.jupiter.api.AssertEquals.assertEquals import org.junit.jupiter.api.AssertionTestUtils.assertEmptyMessage import org.junit.jupiter.api.AssertionTestUtils.assertMessageContains import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals import org.opentest4j.AssertionFailedError import java.util.stream.Stream class KotlinFailAssertionsTests { @Test fun `fail with string`() { val message = "test" val ex = assertThrows { fail(message) } assertMessageEquals(ex, message) } @Test fun `fail with message supplier`() { val message = "test" val ex = assertThrows { fail { message } } assertMessageEquals(ex, message) } @Test fun `fail with null string`() { val ex = assertThrows { fail(null as String?) } assertEmptyMessage(ex) } @Test fun `fail with null message supplier`() { val ex = assertThrows { fail(null as (() -> String)?) } assertEmptyMessage(ex) } @Test fun `fail with string and throwable`() { val message = "message" val throwableCause = "cause" val ex = assertThrows { fail(message, Throwable(throwableCause)) } assertMessageEquals(ex, message) val cause = ex.cause assertMessageContains(cause, throwableCause) } @Test fun `fail with throwable`() { val throwableCause = "cause" val ex = assertThrows { fail(Throwable(throwableCause)) } assertEmptyMessage(ex) val cause = ex.cause assertMessageContains(cause, throwableCause) } @Test fun `fail with string and null throwable`() { val message = "message" val ex = assertThrows { fail(message, null) } assertMessageEquals(ex, message) if (ex.cause != null) { throw AssertionError("Cause should have been null") } } @Test fun `fail with null string and throwable`() { val throwableCause = "cause" val ex = assertThrows { fail(null, Throwable(throwableCause)) } assertEmptyMessage(ex) val cause = ex.cause assertMessageContains(cause, throwableCause) } @Test fun `fail usable as a stream expression`() { val count = Stream.empty() .peek { _ -> fail("peek should never be called") } .filter { _ -> fail("filter should never be called", Throwable("cause")) } .map { _ -> fail(Throwable("map should never be called")) } .sorted { _, _ -> fail { "sorted should never be called" } } .count() assertEquals(0L, count) } @Test fun `fail usable as a sequence expression`() { val count = emptyList() .asSequence() .onEach { _ -> fail("peek should never be called") } .filter { _ -> fail("filter should never be called", Throwable("cause")) } .map { _ -> fail(Throwable("map should never be called")) } .count() assertEquals(0, count) } } junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/engine/000077500000000000000000000000001455764576500272205ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/engine/kotlin/000077500000000000000000000000001455764576500305205ustar00rootroot00000000000000ArbitraryNamingKotlinTestCase.kt000066400000000000000000000014431455764576500367110ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/engine/kotlin/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.kotlin import org.junit.jupiter.api.Test class ArbitraryNamingKotlinTestCase { companion object { @JvmField val METHOD_NAME = "\uD83E\uDD86 ~|~test with a really, (really) terrible name & that needs to be changed!~|~" } @Suppress("DANGEROUS_CHARACTERS") @Test fun `🦆 ~|~test with a really, (really) terrible name & that needs to be changed!~|~`() { } @Test fun `test name ends with parentheses()`() { } } InstancePerClassKotlinTestCase.kt000066400000000000000000000026611455764576500370240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/engine/kotlin/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.kotlin import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS @TestInstance(PER_CLASS) class InstancePerClassKotlinTestCase { companion object { @JvmField val TEST_INSTANCES: MutableMap> = HashMap() } @BeforeAll fun beforeAll() { increment("beforeAll") } @BeforeEach fun beforeEach() { increment("beforeEach") } @AfterEach fun afterEach() { increment("afterEach") } @AfterAll fun afterAll() { increment("afterAll") } @Test fun firstTest() { increment("test") } @Test fun secondTest() { increment("test") } private fun increment(name: String) { TEST_INSTANCES.computeIfAbsent(this, { _ -> HashMap() }) .compute(name, { _, oldValue -> (oldValue ?: 0) + 1 }) } } InstancePerMethodKotlinTestCase.kt000066400000000000000000000027121455764576500371740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/kotlin/org/junit/jupiter/engine/kotlin/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.kotlin import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test class InstancePerMethodKotlinTestCase { companion object { @JvmField val TEST_INSTANCES: MutableMap> = LinkedHashMap() @JvmStatic @BeforeAll fun beforeAll() { increment(this, "beforeAll") } @JvmStatic @AfterAll fun afterAll() { increment(this, "afterAll") } private fun increment(instance: Any, name: String) { TEST_INSTANCES.computeIfAbsent(instance, { _ -> LinkedHashMap() }) .compute(name, { _, oldValue -> (oldValue ?: 0) + 1 }) } } @BeforeEach fun beforeEach() { increment(this, "beforeEach") } @AfterEach fun afterEach() { increment(this, "afterEach") } @Test fun firstTest() { increment(this, "test") } @Test fun secondTest() { increment(this, "test") } } junit5-r5.10.2/junit-jupiter-engine/src/test/resources/000077500000000000000000000000001455764576500230635ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/resources/META-INF/000077500000000000000000000000001455764576500242235ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/resources/META-INF/services/000077500000000000000000000000001455764576500260465ustar00rootroot00000000000000org.junit.jupiter.api.extension.Extension000066400000000000000000000000721455764576500360470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/test/resources/META-INF/servicesorg.junit.jupiter.engine.extension.ServiceLoaderExtension junit5-r5.10.2/junit-jupiter-engine/src/test/resources/jupiter-testjar.jar000066400000000000000000000043131455764576500267160ustar00rootroot00000000000000PK Cz"Jcom/UT ajX;ajXux PK Cz"J com/example/UT ajX;ajXux PK Cz"Jcom/example/project/UT ajX;ajXux PKy"J0ޣk#com/example/project/FirstTest.classUT `jXajXux TRU~öZ+BIR_U ŦZ 2CrC7{ݳ K?8Jo9I 4ifg}?xR\uQ.`Wǵp= F:Z<>t񑋏Q2w +[r˺)U$׳ֶL6vHM"rO3{*upЭ@~/Zq(8aUfS`>̕: 3V3VF&U`͵hGW-IwP F *@GXfO7D$KOȨRb{KQ0JGM @ls}+*C^g z0#mkm15omW?Cn J7.W@v h!W٣֕66#R, f' Ot6}]&B;]cڤ&qt|_L`ǽ zXƊ Ϻ/gW-+~C' ¶遻ZǤ<ڶFh6vVԸ `)Meқ':}ŋ<͵ə{ JsbϮ Z^QaE -8T.Jt~>I*[.jb;x2wvS;=\<',&m(rh#mDם5C lݒc+psk1>G}7?| x:*PxI"X*ODK%3lc-#1$Q+͵T1v}.eNiњH-R'+I%odfE$,Ipa2:_g󔇹),#9U4v/)wa+3wŧV <ľ!C ܒOŔg'ZCw)GY&Ҳ/cȯcxqh~%$|NB!jpJƢdF&+thg7}C B:Nsp~A0sn6zs+clQFd\/-zE 36H7hSj{+HDޠ )ᛤ([h7PK Cz"JAcom/UTajXux PK Cz"J A>com/example/UTajXux PK Cz"JAcom/example/project/UTajXux PKy"J0ޣk#com/example/project/FirstTest.classUT`jXux PKy"J%^$com/example/project/SecondTest.classUT`jXux PKjunit5-r5.10.2/junit-jupiter-engine/src/test/resources/log4j2-test.xml000066400000000000000000000012771455764576500256720ustar00rootroot00000000000000 junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/000077500000000000000000000000001455764576500226035ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/000077500000000000000000000000001455764576500235245ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/000077500000000000000000000000001455764576500243135ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500254445ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/junit/jupiter/000077500000000000000000000000001455764576500271265ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/junit/jupiter/engine/000077500000000000000000000000001455764576500303735ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/junit/jupiter/engine/discovery/000077500000000000000000000000001455764576500324025ustar00rootroot00000000000000JupiterUniqueIdBuilder.java000066400000000000000000000047251455764576500375730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-engine/src/testFixtures/java/org/junit/jupiter/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.engine.discovery; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor; import org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor; import org.junit.platform.engine.UniqueId; /** * Test data builder for unique IDs for JupiterTestEngine. * * Used to decouple tests from concrete unique ID strings. * * @since 5.0 */ public class JupiterUniqueIdBuilder { public static UniqueId uniqueIdForClass(Class clazz) { UniqueId containerId = engineId(); if (isInnerClass(clazz)) { containerId = uniqueIdForClass(clazz.getEnclosingClass()); return containerId.append(NestedClassTestDescriptor.SEGMENT_TYPE, clazz.getSimpleName()); } return containerId.append(ClassTestDescriptor.SEGMENT_TYPE, clazz.getName()); } public static UniqueId uniqueIdForTopLevelClass(String className) { return engineId().append(ClassTestDescriptor.SEGMENT_TYPE, className); } public static UniqueId uniqueIdForMethod(Class clazz, String methodPart) { return uniqueIdForClass(clazz).append(TestMethodTestDescriptor.SEGMENT_TYPE, methodPart); } public static UniqueId uniqueIdForTestFactoryMethod(Class clazz, String methodPart) { return uniqueIdForClass(clazz).append(TestFactoryTestDescriptor.SEGMENT_TYPE, methodPart); } public static UniqueId uniqueIdForTestTemplateMethod(Class clazz, String methodPart) { return uniqueIdForClass(clazz).append(TestTemplateTestDescriptor.SEGMENT_TYPE, methodPart); } public static UniqueId appendTestTemplateInvocationSegment(UniqueId parentId, int index) { return parentId.append(TestTemplateInvocationTestDescriptor.SEGMENT_TYPE, "#" + index); } public static UniqueId engineId() { return UniqueId.forEngine(JupiterEngineDescriptor.ENGINE_ID); } } junit5-r5.10.2/junit-jupiter-migrationsupport/000077500000000000000000000000001455764576500214645ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/README.md000066400000000000000000000016711455764576500227500ustar00rootroot00000000000000# Module junit-jupiter-migrationsupport This module provides support for JUnit 4 rules within JUnit Jupiter. Currently, this support is limited to subclasses of the ```org.junit.rules.Verifier``` and ```org.junit.rules.ExternalResource``` rules of JUnit 4, respectively. Please note that a general support for arbitrary ```org.junit.rules.TestRule``` implementations is not possible within the JUnit Jupiter extension model. The main purpose of this module is to facilitate the migration of large JUnit 4 codebases containing such JUnit 4 rules by minimizing the effort needed to run such legacy tests under JUnit 5. By using one of the two provided class-level extensions on a test class such rules in legacy code bases can be left unchanged including the JUnit 4 rule import statements. However, if you intend to develop a *new* extension for JUnit 5 please use the new extension model of JUnit Jupiter instead of the rule-based model of JUnit 4. junit5-r5.10.2/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts000066400000000000000000000017411455764576500317040ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") } description = "JUnit Jupiter Migration Support" dependencies { api(platform(projects.junitBom)) api(libs.junit4) api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) testImplementation(projects.junitJupiterEngine) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(projects.junitPlatformTestkit) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks.jar { bundle { val importAPIGuardian: String by extra bnd(""" # Import JUnit4 packages with a version Import-Package: \ $importAPIGuardian,\ org.junit;version="[${libs.versions.junit4Min.get()},5)",\ org.junit.platform.commons.logging;status=INTERNAL,\ org.junit.rules;version="[${libs.versions.junit4Min.get()},5)",\ * """) } } junit5-r5.10.2/junit-jupiter-migrationsupport/src/000077500000000000000000000000001455764576500222535ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/000077500000000000000000000000001455764576500231775ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/000077500000000000000000000000001455764576500241205ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/000077500000000000000000000000001455764576500247075ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/000077500000000000000000000000001455764576500260405ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/000077500000000000000000000000001455764576500275225ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/000077500000000000000000000000001455764576500331505ustar00rootroot00000000000000EnableJUnit4MigrationSupport.java000066400000000000000000000042761455764576500414400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.migrationsupport.conditions.IgnoreCondition; import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; import org.junit.jupiter.migrationsupport.rules.ExpectedExceptionSupport; import org.junit.jupiter.migrationsupport.rules.ExternalResourceSupport; import org.junit.jupiter.migrationsupport.rules.VerifierSupport; /** * {@code EnableJUnit4MigrationSupport} is a class-level annotation that * enables all JUnit 4 migration support within JUnit Jupiter. * *

Specifically, this annotation registers all extensions supported by * {@link EnableRuleMigrationSupport @EnableRuleMigrationSupport} and provides * support for JUnit 4's {@link org.junit.Ignore @Ignore} annotation for * disabling test classes and test methods. * *

Technically speaking, {@code @EnableJUnit4MigrationSupport} is a composed * annotation which registers all of the following migration extensions: * {@link VerifierSupport}, {@link ExternalResourceSupport}, * {@link ExpectedExceptionSupport}, and {@link IgnoreCondition}. Note, however, * that you can optionally register one or more of these extensions explicitly * without the use of this composed annotation. * * @since 5.4 * @see ExternalResourceSupport * @see VerifierSupport * @see ExpectedExceptionSupport * @see IgnoreCondition * @see EnableRuleMigrationSupport */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @API(status = STABLE, since = "5.7") @EnableRuleMigrationSupport @ExtendWith(IgnoreCondition.class) public @interface EnableJUnit4MigrationSupport { } conditions/000077500000000000000000000000001455764576500352425ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupportIgnoreCondition.java000066400000000000000000000041261455764576500412020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.conditions; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import java.lang.reflect.AnnotatedElement; import org.apiguardian.api.API; import org.junit.Ignore; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.util.StringUtils; /** * {@link ExecutionCondition} that supports JUnit 4's {@link Ignore @Ignore} * annotation. * * @since 5.4 * @see org.junit.Ignore @Ignore * @see org.junit.jupiter.api.Disabled @Disabled * @see #evaluateExecutionCondition(ExtensionContext) * @see org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport */ @API(status = STABLE, since = "5.7") public class IgnoreCondition implements ExecutionCondition { private static final ConditionEvaluationResult ENABLED = // ConditionEvaluationResult.enabled("@org.junit.Ignore is not present"); public IgnoreCondition() { } /** * Containers/tests are disabled if {@link Ignore @Ignore} is present on * the test class or method. */ @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { AnnotatedElement element = context.getElement().orElse(null); return findAnnotation(element, Ignore.class) // .map(annotation -> toResult(element, annotation)) // .orElse(ENABLED); } private ConditionEvaluationResult toResult(AnnotatedElement element, Ignore annotation) { String value = annotation.value(); String reason = StringUtils.isNotBlank(value) ? value : element + " is disabled via @org.junit.Ignore"; return ConditionEvaluationResult.disabled(reason); } } package-info.java000066400000000000000000000003531455764576500404320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/** * Extensions which provide support for conditional test execution features of * JUnit 4 (e.g., the {@link org.junit.Ignore @Ignore} annotation) within JUnit * Jupiter. */ package org.junit.jupiter.migrationsupport.conditions; package-info.java000066400000000000000000000001551455764576500362610ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/** * Support for migrating from JUnit 4 to JUnit Jupiter. */ package org.junit.jupiter.migrationsupport; rules/000077500000000000000000000000001455764576500342235ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupportEnableRuleMigrationSupport.java000066400000000000000000000030261455764576500423540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtendWith; /** * This class-level annotation enables native JUnit 4 rule support * within JUnit Jupiter. * *

Currently, rules of type {@code Verifier}, {@code ExternalResource}, * and {@code ExpectedException} rules are supported. * *

{@code @EnableRuleMigrationSupport} is a composed annotation which * enables all supported extensions: {@link VerifierSupport}, * {@link ExternalResourceSupport}, and {@link ExpectedExceptionSupport}. * * @since 5.0 * @see ExternalResourceSupport * @see VerifierSupport * @see ExpectedExceptionSupport * @see org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @API(status = STABLE, since = "5.7") @ExtendWith(ExternalResourceSupport.class) @ExtendWith(VerifierSupport.class) @ExtendWith(ExpectedExceptionSupport.class) public @interface EnableRuleMigrationSupport { } ExpectedExceptionSupport.java000066400000000000000000000046751455764576500421170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; import org.junit.jupiter.migrationsupport.rules.adapter.ExpectedExceptionAdapter; import org.junit.rules.ExpectedException; /** * This {@code Extension} provides native support for the * {@link ExpectedException} rule from JUnit 4. * *

By using this class-level extension on a test class, * {@code ExpectedException} can continue to be used. * *

However, you should rather switch to * {@link org.junit.jupiter.api.Assertions#assertThrows} for new code. * * @since 5.0 * @see org.junit.jupiter.api.Assertions#assertThrows * @see org.junit.rules.ExpectedException * @see org.junit.rules.TestRule * @see org.junit.Rule */ @API(status = STABLE, since = "5.7") public class ExpectedExceptionSupport implements AfterEachCallback, TestExecutionExceptionHandler { private static final String EXCEPTION_WAS_HANDLED = "exceptionWasHandled"; private final TestRuleSupport support = new TestRuleSupport(ExpectedExceptionAdapter::new, ExpectedException.class); public ExpectedExceptionSupport() { } @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { getStore(context).put(EXCEPTION_WAS_HANDLED, TRUE); this.support.handleTestExecutionException(context, throwable); } @Override public void afterEach(ExtensionContext context) throws Exception { boolean handled = getStore(context).getOrComputeIfAbsent(EXCEPTION_WAS_HANDLED, key -> FALSE, Boolean.class); if (!handled) { this.support.afterEach(context); } } private Store getStore(ExtensionContext context) { return context.getStore(Namespace.create(getClass(), context.getUniqueId())); } } ExternalResourceSupport.java000066400000000000000000000036631455764576500417650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.migrationsupport.rules.adapter.ExternalResourceAdapter; import org.junit.rules.ExternalResource; /** * This {@code Extension} provides native support for subclasses of * the {@link ExternalResource} rule from JUnit 4. * *

{@code @Rule}-annotated fields as well as methods are supported. * *

By using this class-level extension on a test class such * {@code ExternalResource} implementations in legacy code bases * can be left unchanged including the JUnit 4 rule import statements. * *

However, if you intend to develop a new extension for * JUnit 5 please use the new extension model of JUnit Jupiter instead * of the rule-based model of JUnit 4. * * @since 5.0 * @see org.junit.rules.ExternalResource * @see org.junit.rules.TestRule * @see org.junit.Rule */ @API(status = STABLE, since = "5.7") public class ExternalResourceSupport implements BeforeEachCallback, AfterEachCallback { private final TestRuleSupport support = new TestRuleSupport(ExternalResourceAdapter::new, ExternalResource.class); public ExternalResourceSupport() { } @Override public void beforeEach(ExtensionContext context) throws Exception { this.support.beforeEach(context); } @Override public void afterEach(ExtensionContext context) throws Exception { this.support.afterEach(context); } } TestRuleSupport.java000066400000000000000000000143161455764576500402370ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static java.util.Collections.unmodifiableList; import static org.junit.platform.commons.util.AnnotationUtils.findPublicAnnotatedFields; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Predicate; import org.junit.Rule; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; import org.junit.jupiter.migrationsupport.rules.adapter.AbstractTestRuleAdapter; import org.junit.jupiter.migrationsupport.rules.adapter.GenericBeforeAndAfterAdvice; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedField; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMethod; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.rules.TestRule; /** * @since 5.0 */ class TestRuleSupport implements BeforeEachCallback, TestExecutionExceptionHandler, AfterEachCallback { private final Class ruleType; private final Function adapterGenerator; TestRuleSupport(Function adapterGenerator, Class ruleType) { this.adapterGenerator = adapterGenerator; this.ruleType = ruleType; } /** * @see org.junit.runners.BlockJUnit4ClassRunner#withRules * @see org.junit.rules.RunRules */ @SuppressWarnings("JavadocReference") private List findRuleAnnotatedMembers(Object testInstance) { List result = new ArrayList<>(); // @formatter:off // Instantiate rules from methods by calling them findAnnotatedMethods(testInstance).stream() .map(method -> new TestRuleAnnotatedMethod(testInstance, method)) .forEach(result::add); // Fields are already instantiated because we have a test instance findAnnotatedFields(testInstance).stream() .map(field -> new TestRuleAnnotatedField(testInstance, field)) .forEach(result::add); // @formatter:on // Due to how rules are applied (see RunRules), the last rule gets called first. // Rules from fields get called before those from methods. // Thus, we first add methods and then fields and reverse the list in the end. Collections.reverse(result); return unmodifiableList(result); } private List findAnnotatedMethods(Object testInstance) { Predicate isRuleMethod = method -> isAnnotated(method, Rule.class); Predicate hasCorrectReturnType = method -> TestRule.class.isAssignableFrom(method.getReturnType()); return findMethods(testInstance.getClass(), isRuleMethod.and(hasCorrectReturnType)); } private List findAnnotatedFields(Object testInstance) { return findPublicAnnotatedFields(testInstance.getClass(), TestRule.class, Rule.class); } @Override public void beforeEach(ExtensionContext context) { invokeAppropriateMethodOnRuleAnnotatedMembers(context, false, GenericBeforeAndAfterAdvice::before); } @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { int numRuleAnnotatedMembers = invokeAppropriateMethodOnRuleAnnotatedMembers(context, true, advice -> advice.handleTestExecutionException(throwable)); // If no appropriate @Rule annotated members were discovered, we then // have to rethrow the exception in order not to silently swallow it. // Fixes bug: https://github.com/junit-team/junit5/issues/1069 if (numRuleAnnotatedMembers == 0) { throw throwable; } } @Override public void afterEach(ExtensionContext context) { invokeAppropriateMethodOnRuleAnnotatedMembers(context, true, GenericBeforeAndAfterAdvice::after); } /** * @return the number of appropriate rule-annotated members that were discovered */ private int invokeAppropriateMethodOnRuleAnnotatedMembers(ExtensionContext context, boolean reverseOrder, AdviceInvoker adviceInvoker) { List ruleAnnotatedMembers = getRuleAnnotatedMembers(context); if (reverseOrder) { Collections.reverse(ruleAnnotatedMembers); } AtomicInteger counter = new AtomicInteger(); // @formatter:off ruleAnnotatedMembers.stream() .filter(annotatedMember -> this.ruleType.isInstance(annotatedMember.getTestRule())) .map(this.adapterGenerator) .forEach(advice -> { adviceInvoker.invokeAndMaskCheckedExceptions(advice); counter.incrementAndGet(); }); // @formatter:on return counter.get(); } /** * @return a modifiable copy of the list of rule-annotated members */ @SuppressWarnings("unchecked") private List getRuleAnnotatedMembers(ExtensionContext context) { Object testInstance = context.getRequiredTestInstance(); Namespace namespace = Namespace.create(TestRuleSupport.class, context.getRequiredTestClass()); // @formatter:off return new ArrayList<>(context.getStore(namespace) .getOrComputeIfAbsent("rule-annotated-members", key -> findRuleAnnotatedMembers(testInstance), List.class)); // @formatter:on } @FunctionalInterface private interface AdviceInvoker { default void invokeAndMaskCheckedExceptions(GenericBeforeAndAfterAdvice advice) { try { invoke(advice); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(t); } } void invoke(GenericBeforeAndAfterAdvice advice) throws Throwable; } } VerifierSupport.java000066400000000000000000000032441455764576500402410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.migrationsupport.rules.adapter.VerifierAdapter; import org.junit.rules.Verifier; /** * This {@code Extension} provides native support for subclasses of * the {@link Verifier} rule from JUnit 4. * *

{@code @Rule}-annotated fields as well as methods are supported. * *

By using this class-level extension on a test class such * {@code Verifier} implementations in legacy code bases * can be left unchanged including the JUnit 4 rule import statements. * *

However, if you intend to develop a new extension for * JUnit 5 please use the new extension model of JUnit Jupiter instead * of the rule-based model of JUnit 4. * * @since 5.0 * @see org.junit.rules.Verifier * @see org.junit.rules.TestRule * @see org.junit.Rule */ @API(status = STABLE, since = "5.7") public class VerifierSupport implements AfterEachCallback { private final TestRuleSupport support = new TestRuleSupport(VerifierAdapter::new, Verifier.class); public VerifierSupport() { } @Override public void afterEach(ExtensionContext context) throws Exception { this.support.afterEach(context); } } adapter/000077500000000000000000000000001455764576500356435ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rulesAbstractTestRuleAdapter.java000066400000000000000000000036511455764576500432470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.adapter; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import static org.junit.platform.commons.util.ReflectionUtils.invokeMethod; import java.lang.reflect.Method; import org.apiguardian.api.API; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.rules.TestRule; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public abstract class AbstractTestRuleAdapter implements GenericBeforeAndAfterAdvice { private final TestRule target; public AbstractTestRuleAdapter(TestRuleAnnotatedMember annotatedMember, Class adapteeClass) { this.target = annotatedMember.getTestRule(); Preconditions.condition(adapteeClass.isAssignableFrom(this.target.getClass()), () -> adapteeClass + " is not assignable from " + this.target.getClass()); } protected Object executeMethod(String name) { return executeMethod(name, new Class[0]); } protected Object executeMethod(String methodName, Class[] parameterTypes, Object... arguments) { Method method = findMethod(this.target.getClass(), methodName, parameterTypes).orElseThrow( () -> new JUnitException(String.format("Failed to find method %s(%s) in class %s", methodName, ClassUtils.nullSafeToString(parameterTypes), this.target.getClass().getName()))); return invokeMethod(method, this.target, arguments); } } ExpectedExceptionAdapter.java000066400000000000000000000022741455764576500434340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.adapter; import static java.lang.Boolean.TRUE; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.rules.ExpectedException; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class ExpectedExceptionAdapter extends AbstractTestRuleAdapter { public ExpectedExceptionAdapter(TestRuleAnnotatedMember annotatedMember) { super(annotatedMember, ExpectedException.class); } @Override public void handleTestExecutionException(Throwable cause) throws Throwable { executeMethod("handleException", new Class[] { Throwable.class }, cause); } @Override public void after() { if (TRUE.equals(executeMethod("isAnyExceptionExpected"))) { executeMethod("failDueToMissingException"); } } } ExternalResourceAdapter.java000066400000000000000000000017221455764576500433030ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.adapter; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.rules.ExternalResource; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class ExternalResourceAdapter extends AbstractTestRuleAdapter { public ExternalResourceAdapter(TestRuleAnnotatedMember annotatedMember) { super(annotatedMember, ExternalResource.class); } @Override public void before() { executeMethod("before"); } @Override public void after() { executeMethod("after"); } } GenericBeforeAndAfterAdvice.java000066400000000000000000000013121455764576500437230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.adapter; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public interface GenericBeforeAndAfterAdvice { default void before() { } default void handleTestExecutionException(Throwable cause) throws Throwable { } default void after() { } } VerifierAdapter.java000066400000000000000000000015611455764576500415650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.adapter; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.rules.Verifier; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public class VerifierAdapter extends AbstractTestRuleAdapter { public VerifierAdapter(TestRuleAnnotatedMember annotatedMember) { super(annotatedMember, Verifier.class); } @Override public void after() { executeMethod("verify"); } } package-info.java000066400000000000000000000002531455764576500410320ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/** * Simple wrappers for JUnit 4 rules to overcome visibility limitations of the JUnit 4 implementations. */ package org.junit.jupiter.migrationsupport.rules.adapter; member/000077500000000000000000000000001455764576500354725ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rulesAbstractTestRuleAnnotatedMember.java000066400000000000000000000013051455764576500445550ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.member; import org.junit.rules.TestRule; /** * @since 5.0 */ abstract class AbstractTestRuleAnnotatedMember implements TestRuleAnnotatedMember { private final TestRule testRule; AbstractTestRuleAnnotatedMember(TestRule testRule) { this.testRule = testRule; } @Override public TestRule getTestRule() { return this.testRule; } } TestRuleAnnotatedField.java000066400000000000000000000022531455764576500427100ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.member; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.makeAccessible; import java.lang.reflect.Field; import org.apiguardian.api.API; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.rules.TestRule; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.1") public final class TestRuleAnnotatedField extends AbstractTestRuleAnnotatedMember { public TestRuleAnnotatedField(Object testInstance, Field field) { super(retrieveTestRule(testInstance, field)); } private static TestRule retrieveTestRule(Object testInstance, Field field) { try { return (TestRule) makeAccessible(field).get(testInstance); } catch (IllegalAccessException exception) { throw ExceptionUtils.throwAsUncheckedException(exception); } } } TestRuleAnnotatedMember.java000066400000000000000000000011641455764576500430740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.member; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.rules.TestRule; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public interface TestRuleAnnotatedMember { TestRule getTestRule(); } TestRuleAnnotatedMethod.java000066400000000000000000000015601455764576500431050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules.member; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Method; import org.apiguardian.api.API; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.rules.TestRule; /** * @since 5.0 */ @API(status = INTERNAL, since = "5.1") public final class TestRuleAnnotatedMethod extends AbstractTestRuleAnnotatedMember { public TestRuleAnnotatedMethod(Object testInstance, Method method) { super((TestRule) ReflectionUtils.invokeMethod(method, testInstance)); } } package-info.java000066400000000000000000000002201455764576500406530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/** * Abstractions for members which can be targets of JUnit 4 rule annotations. */ package org.junit.jupiter.migrationsupport.rules.member; package-info.java000066400000000000000000000002211455764576500374050ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/** * Extensions which provide (limited) support for JUnit 4 rules within JUnit Jupiter. */ package org.junit.jupiter.migrationsupport.rules; junit5-r5.10.2/junit-jupiter-migrationsupport/src/module/000077500000000000000000000000001455764576500235405ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/module/org.junit.jupiter.migrationsupport/000077500000000000000000000000001455764576500325655ustar00rootroot00000000000000module-info.java000066400000000000000000000015541455764576500355740ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/module/org.junit.jupiter.migrationsupport/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Support for migrating from JUnit 4 to JUnit Jupiter. * * @since 5.0 */ module org.junit.jupiter.migrationsupport { requires transitive junit; // 4 requires static transitive org.apiguardian.api; requires transitive org.junit.jupiter.api; requires org.junit.platform.commons; exports org.junit.jupiter.migrationsupport; exports org.junit.jupiter.migrationsupport.conditions; exports org.junit.jupiter.migrationsupport.rules; exports org.junit.jupiter.migrationsupport.rules.adapter; exports org.junit.jupiter.migrationsupport.rules.member; } junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/000077500000000000000000000000001455764576500232325ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/000077500000000000000000000000001455764576500241535ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/000077500000000000000000000000001455764576500247425ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/000077500000000000000000000000001455764576500260735ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/000077500000000000000000000000001455764576500275555ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/000077500000000000000000000000001455764576500332035ustar00rootroot00000000000000JupiterMigrationSupportTestSuite.java000066400000000000000000000022231455764576500425310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; /** * Test suite for JUnit Jupiter migration support. * *

Logging Configuration

* *

In order for our log4j2 configuration to be used in an IDE, you must * set the following system property before running any tests — for * example, in Run Configurations in Eclipse. * *

 * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
 * 
* * @since 5.0 */ @Suite @SelectPackages("org.junit.jupiter.migrationsupport") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") class JupiterMigrationSupportTestSuite { } conditions/000077500000000000000000000000001455764576500352755ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupportIgnoreAnnotationIntegrationTests.java000066400000000000000000000041411455764576500446450ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/conditions/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.conditions; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import java.util.ArrayList; import java.util.List; import org.junit.Ignore; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport; /** * Empirical integration tests for JUnit 4's {@link Ignore @Ignore} support in * JUnit Jupiter, covering the {@link IgnoreCondition} and * {@link EnableJUnit4MigrationSupport @EnableJUnit4MigrationSupport}. * * @since 5.4 * @see IgnoreConditionTests */ class IgnoreAnnotationIntegrationTests { @Nested @ExtendWith(IgnoreCondition.class) class ExplicitIgnoreConditionRegistration extends BaseNestedTestCase { } @Nested @EnableJUnit4MigrationSupport class ImplicitIgnoreConditionRegistration extends BaseNestedTestCase { } @TestInstance(PER_CLASS) private static abstract class BaseNestedTestCase { private static List tests = new ArrayList<>(); @BeforeAll void clearTracking() { tests.clear(); } @AfterAll void verifyTracking() { assertThat(tests).containsExactly("notIgnored"); } @BeforeEach void track(TestInfo testInfo) { tests.add(testInfo.getTestMethod().get().getName()); } @Test @Ignore void ignored() { fail("This method should have been disabled via @Ignore"); } @Test // @Ignore void notIgnored() { /* no-op */ } } } IgnoreConditionTests.java000066400000000000000000000112131455764576500422530ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/conditions/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.conditions; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import org.junit.Ignore; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; /** * Integration tests for JUnit 4's {@link Ignore @Ignore} support in JUnit * Jupiter provided by the {@link IgnoreCondition}. * * @since 5.4 * @see IgnoreAnnotationIntegrationTests */ class IgnoreConditionTests { @Test void ignoredTestClassWithDefaultMessage() { Class testClass = IgnoredClassWithDefaultMessageTestCase.class; // @formatter:off executeTestsForClass(testClass).allEvents().assertEventsMatchExactly( event(engine(), started()), event(container(testClass), skippedWithReason(testClass + " is disabled via @org.junit.Ignore")), event(engine(), finishedSuccessfully()) ); // @formatter:on } @Test void ignoredTestClassWithCustomMessage() { Class testClass = IgnoredClassWithCustomMessageTestCase.class; // @formatter:off executeTestsForClass(testClass).allEvents().assertEventsMatchExactly( event(engine(), started()), event(container(testClass), skippedWithReason("Ignored Class")), event(engine(), finishedSuccessfully()) ); // @formatter:on } @Test void ignoredAndNotIgnoredTestMethods() { EngineExecutionResults executionResults = executeTestsForClass(IgnoredMethodsTestCase.class); Events containers = executionResults.containerEvents(); Events tests = executionResults.testEvents(); // executionResults.allEvents().debug(); // executionResults.allEvents().debug(System.err); // containers.debug(); // tests.debug(System.err); // tests.debug(); // tests.skipped().debug(); // tests.started().debug(); // tests.succeeded().debug(); // executionResults.allEvents().executions().debug(); // containers.executions().debug(); // tests.executions().debug(); executionResults.allEvents().executions().assertThatExecutions().hasSize(5); containers.executions().assertThatExecutions().hasSize(2); tests.executions().assertThatExecutions().hasSize(3); // @formatter:off // tests.debug().assertEventsMatchExactly( tests.assertEventsMatchExactly( event(test("ignoredWithCustomMessage"), skippedWithReason("Ignored Method")), event(test("notIgnored"), started()), event(test("notIgnored"), finishedSuccessfully()), event(test("ignoredWithDefaultMessage"), skippedWithReason( reason -> reason.endsWith("ignoredWithDefaultMessage() is disabled via @org.junit.Ignore"))) ); // @formatter:on } private EngineExecutionResults executeTestsForClass(Class testClass) { return EngineTestKit.execute("junit-jupiter", request().selectors(selectClass(testClass)).build()); } // ------------------------------------------------------------------------- @ExtendWith(IgnoreCondition.class) @Ignore static class IgnoredClassWithDefaultMessageTestCase { @Test void ignoredBecauseClassIsIgnored() { /* no-op */ } } @ExtendWith(IgnoreCondition.class) @Ignore("Ignored Class") static class IgnoredClassWithCustomMessageTestCase { @Test void ignoredBecauseClassIsIgnored() { /* no-op */ } } @ExtendWith(IgnoreCondition.class) static class IgnoredMethodsTestCase { @Test void notIgnored() { /* no-op */ } @Test @Ignore void ignoredWithDefaultMessage() { fail("This method should have been disabled via @Ignore"); } @Test @Ignore("Ignored Method") void ignoredWithCustomMessage() { fail("This method should have been disabled via @Ignore"); } } } rules/000077500000000000000000000000001455764576500342565ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupportAbstractTestRuleAdapterTests.java000066400000000000000000000050521455764576500427020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; import org.junit.jupiter.migrationsupport.rules.adapter.AbstractTestRuleAdapter; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.rules.ErrorCollector; import org.junit.rules.TemporaryFolder; import org.junit.rules.TestRule; import org.junit.rules.Verifier; /** * @since 5.0 */ public class AbstractTestRuleAdapterTests { @Test void constructionWithAssignableArgumentsIsSuccessful() { new TestableTestRuleAdapter(new SimpleRuleAnnotatedMember(new ErrorCollector()), Verifier.class); } @Test void constructionWithUnassignableArgumentsFails() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> new TestableTestRuleAdapter(new SimpleRuleAnnotatedMember(new TemporaryFolder()), Verifier.class)); assertEquals(exception.getMessage(), "class org.junit.rules.Verifier is not assignable from class org.junit.rules.TemporaryFolder"); } @Test void exceptionsDuringMethodLookupAreWrappedAndThrown() { AbstractTestRuleAdapter adapter = new AbstractTestRuleAdapter( new SimpleRuleAnnotatedMember(new ErrorCollector()), Verifier.class) { @Override public void before() { super.executeMethod("foo"); } }; JUnitException exception = assertThrows(JUnitException.class, adapter::before); assertEquals(exception.getMessage(), "Failed to find method foo() in class org.junit.rules.ErrorCollector"); } private static class TestableTestRuleAdapter extends AbstractTestRuleAdapter { TestableTestRuleAdapter(TestRuleAnnotatedMember annotatedMember, Class adapteeClass) { super(annotatedMember, adapteeClass); } } private static class SimpleRuleAnnotatedMember implements TestRuleAnnotatedMember { private final TestRule testRule; SimpleRuleAnnotatedMember(TestRule testRule) { this.testRule = testRule; } @Override public TestRule getTestRule() { return this.testRule; } } } EnableRuleMigrationSupportWithBothRuleTypesTests.java000066400000000000000000000042161455764576500467620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.rules.ExternalResource; import org.junit.rules.Verifier; @EnableRuleMigrationSupport public class EnableRuleMigrationSupportWithBothRuleTypesTests { private static boolean afterOfRule1WasExecuted = false; private static boolean beforeOfRule2WasExecuted = false; private static boolean afterOfRule2WasExecuted = false; private static int numberOfRule1InstancesCreated = 0; private static int numberOfRule2InstancesCreated = 0; @Rule public Verifier verifier1 = new Verifier() { { numberOfRule1InstancesCreated++; } @Override protected void verify() { afterOfRule1WasExecuted = true; } }; @Rule public ExternalResource getResource2() { return new ExternalResource() { { numberOfRule2InstancesCreated++; } private Object instance; @Override protected void before() { instance = this; beforeOfRule2WasExecuted = true; } @Override protected void after() { assertNotNull(instance); assertSame(instance, this); afterOfRule2WasExecuted = true; } }; } @Test void beforeMethodOfBothRule2WasExecuted() { assertTrue(beforeOfRule2WasExecuted); } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { assertEquals(1, numberOfRule1InstancesCreated); assertEquals(1, numberOfRule2InstancesCreated); if (!afterOfRule1WasExecuted) fail(); if (!afterOfRule2WasExecuted) fail(); } } ExpectedExceptionSupportTests.java000066400000000000000000000077531455764576500431750ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.io.IOException; import org.junit.Rule; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; import org.junit.rules.ExpectedException; /** * Integration tests for {@link ExpectedExceptionSupport}. * * @since 5.0 */ class ExpectedExceptionSupportTests { @Test void expectedExceptionIsProcessedCorrectly() { Events tests = executeTestsForClass(ExpectedExceptionTestCase.class); tests.assertStatistics(stats -> stats.started(4).succeeded(1).aborted(0).failed(3)); tests.succeeded().assertThatEvents().have( event(test("correctExceptionExpectedThrown"), finishedSuccessfully())); tests.failed().assertThatEvents()// .haveExactly(1, // event(test("noExceptionExpectedButThrown"), // finishedWithFailure(message("no exception expected")))) // .haveExactly(1, // event(test("exceptionExpectedButNotThrown"), // finishedWithFailure(instanceOf(AssertionError.class), // message("Expected test to throw an instance of java.lang.RuntimeException")))) // .haveExactly(1, // event(test("wrongExceptionExpected"), // finishedWithFailure(instanceOf(AssertionError.class), // message(value -> value.contains("Expected: an instance of java.io.IOException"))))); } @Test void expectedExceptionSupportWithoutExpectedExceptionRule() { Class testClass = ExpectedExceptionSupportWithoutExpectedExceptionRuleTestCase.class; Events tests = executeTestsForClass(testClass); tests.assertStatistics(stats -> stats.started(2).succeeded(1).aborted(0).failed(1)); tests.succeeded().assertThatEvents().have(event(test("success"), finishedSuccessfully())); tests.failed().assertThatEvents()// .haveExactly(1, event(test("failure"), finishedWithFailure(message("must fail")))); } private Events executeTestsForClass(Class testClass) { return EngineTestKit.execute("junit-jupiter", request().selectors(selectClass(testClass)).build()).testEvents(); } @ExtendWith(ExpectedExceptionSupport.class) static class ExpectedExceptionTestCase { @SuppressWarnings("deprecation") @Rule public ExpectedException thrown = ExpectedException.none(); @Test void noExceptionExpectedButThrown() { throw new RuntimeException("no exception expected"); } @Test void exceptionExpectedButNotThrown() { thrown.expect(RuntimeException.class); } @Test void wrongExceptionExpected() { thrown.expect(IOException.class); throw new RuntimeException("wrong exception"); } @Test void correctExceptionExpectedThrown() { thrown.expect(RuntimeException.class); throw new RuntimeException("right exception"); } } @ExtendWith(ExpectedExceptionSupport.class) static class ExpectedExceptionSupportWithoutExpectedExceptionRuleTestCase { @Test void success() { /* no-op */ } @Test void failure() { fail("must fail"); } } } ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java000066400000000000000000000036331455764576500522220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; import org.junit.rules.TestRule; @ExtendWith(ExternalResourceSupport.class) class ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests { private static boolean beforeOfRule1WasExecuted = false; private static boolean beforeOfRule2WasExecuted = false; private static boolean afterOfRule1WasExecuted = false; private static boolean afterOfRule2WasExecuted = false; @Rule public MyExternalResource1 getResource1() { return new MyExternalResource1(); } @Rule public TestRule getResource2() { return new ExternalResource() { @Override protected void before() { beforeOfRule2WasExecuted = true; } @Override protected void after() { afterOfRule2WasExecuted = true; } }; } @Test void beforeMethodsOfBothRulesWereExecuted() { assertTrue(beforeOfRule1WasExecuted); assertTrue(beforeOfRule2WasExecuted); } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { if (!afterOfRule1WasExecuted) fail(); if (!afterOfRule2WasExecuted) fail(); } private static class MyExternalResource1 extends ExternalResource { @Override protected void before() { beforeOfRule1WasExecuted = true; } @Override protected void after() { afterOfRule1WasExecuted = true; } } } ExternalResourceSupportForMixedMethodAndFieldRulesTests.java000066400000000000000000000055101455764576500502350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import java.util.ArrayList; import java.util.List; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMixedMethodAndFieldRulesTests { private static List initEvents = new ArrayList<>(); private static List beforeEvents = new ArrayList<>(); private static List afterEvents = new ArrayList<>(); @BeforeAll static void clear() { initEvents.clear(); beforeEvents.clear(); afterEvents.clear(); } @Rule public ExternalResource fieldRule1 = new MyExternalResource("fieldRule1"); @Rule public ExternalResource fieldRule2 = new MyExternalResource("fieldRule2"); @Rule ExternalResource methodRule1() { return new MyExternalResource("methodRule1"); } @Rule ExternalResource methodRule2() { return new MyExternalResource("methodRule2"); } @Test void constructorsAndBeforeEachMethodsOfAllRulesWereExecuted() { assertThat(initEvents).hasSize(4); // the order of fields and methods is not stable, but fields are initialized before methods are called assertThat(initEvents.subList(0, 2)).allMatch(item -> item.startsWith("fieldRule")); assertThat(initEvents.subList(2, 4)).allMatch(item -> item.startsWith("methodRule")); // beforeEach methods of rules from fields are run before those from methods but in reverse order of instantiation assertEquals(asList(initEvents.get(1), initEvents.get(0), initEvents.get(3), initEvents.get(2)), beforeEvents); } @AfterAll static void afterMethodsOfAllRulesWereExecuted() { // beforeEach methods of rules from methods are run before those from fields but in reverse order if (!asList(initEvents.get(2), initEvents.get(3), initEvents.get(0), initEvents.get(1)).equals(afterEvents)) fail(); } static class MyExternalResource extends ExternalResource { private final String name; MyExternalResource(String name) { this.name = name; initEvents.add(name); } @Override protected void before() { beforeEvents.add(name); } @Override protected void after() { afterEvents.add(name); } } } ExternalResourceSupportForMultipleFieldRulesTests.java000066400000000000000000000034051455764576500471770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMultipleFieldRulesTests { private static boolean beforeOfRule1WasExecuted = false; private static boolean beforeOfRule2WasExecuted = false; private static boolean afterOfRule1WasExecuted = false; private static boolean afterOfRule2WasExecuted = false; @Rule public ExternalResource resource1 = new ExternalResource() { @Override protected void before() { beforeOfRule1WasExecuted = true; } @Override protected void after() { afterOfRule1WasExecuted = true; } }; @Rule public ExternalResource resource2 = new ExternalResource() { @Override protected void before() { beforeOfRule2WasExecuted = true; } @Override protected void after() { afterOfRule2WasExecuted = true; } }; @Test void beforeMethodsOfBothRulesWereExecuted() { assertTrue(beforeOfRule1WasExecuted); assertTrue(beforeOfRule2WasExecuted); } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { if (!afterOfRule1WasExecuted) fail(); if (!afterOfRule2WasExecuted) fail(); } } ExternalResourceSupportForMultipleMethodRulesTests.java000066400000000000000000000034721455764576500474000ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMultipleMethodRulesTests { private static boolean beforeOfRule1WasExecuted = false; private static boolean beforeOfRule2WasExecuted = false; private static boolean afterOfRule1WasExecuted = false; private static boolean afterOfRule2WasExecuted = false; @Rule public ExternalResource getResource1() { return new ExternalResource() { @Override protected void before() { beforeOfRule1WasExecuted = true; } @Override protected void after() { afterOfRule1WasExecuted = true; } }; } @Rule public ExternalResource getResource2() { return new ExternalResource() { @Override protected void before() { beforeOfRule2WasExecuted = true; } @Override protected void after() { afterOfRule2WasExecuted = true; } }; } @Test void beforeMethodsOfBothRulesWereExecuted() { assertTrue(beforeOfRule1WasExecuted); assertTrue(beforeOfRule2WasExecuted); } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { if (!afterOfRule1WasExecuted) fail(); if (!afterOfRule2WasExecuted) fail(); } } ExternalResourceSupportForTemporaryFolderFieldTests.java000066400000000000000000000020071455764576500475040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import org.junit.Rule; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.TemporaryFolder; @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForTemporaryFolderFieldTests { private File file; @Rule public TemporaryFolder folder = new TemporaryFolder(); @BeforeEach void setup() throws IOException { this.file = folder.newFile("temp.txt"); } @Test void checkTemporaryFolder() { assertTrue(file.canRead()); } } ExternalResourceSupportWithInheritanceTests.java000066400000000000000000000007561455764576500460510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; public class ExternalResourceSupportWithInheritanceTests extends ExternalResourceSupportForMixedMethodAndFieldRulesTests { } ExternalResourceWithoutAdapterTests.java000066400000000000000000000017171455764576500443310ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.Rule; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.rules.TemporaryFolder; public class ExternalResourceWithoutAdapterTests { @Rule public TemporaryFolder folder = new TemporaryFolder(); @BeforeEach void setup() { try { folder.newFile("temp.txt"); } catch (Exception exception) { assertTrue(exception.getMessage().equals("the temporary folder has not yet been created")); } } @Test void checkTemporaryFolder() { // only needed to invoke testing at all } } FailAfterAllHelper.java000066400000000000000000000011401455764576500405430ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; /** * @since 5.0 */ class FailAfterAllHelper { static void fail() { // hack: use this unrecoverable exception to fail the build, since all others would be swallowed... throw new OutOfMemoryError("a postcondition was violated"); } } LauncherBasedEnableRuleMigrationSupportTests.java000066400000000000000000000065111455764576500460550ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.Rule; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Events; import org.junit.rules.ErrorCollector; import org.junit.rules.ExternalResource; import org.junit.rules.Verifier; class LauncherBasedEnableRuleMigrationSupportTests { @Test void enableRuleMigrationSupportAnnotationWorksForBothRuleTypes() { Events tests = executeTestsForClass(EnableRuleMigrationSupportWithBothRuleTypesTestCase.class); tests.assertStatistics(stats -> stats.started(1).succeeded(1).aborted(0).failed(0)); assertTrue(EnableRuleMigrationSupportWithBothRuleTypesTestCase.afterOfRule1WasExecuted, "after of rule 1 executed?"); assertTrue(EnableRuleMigrationSupportWithBothRuleTypesTestCase.beforeOfRule2WasExecuted, "before of rule 2 executed?"); assertTrue(EnableRuleMigrationSupportWithBothRuleTypesTestCase.afterOfRule2WasExecuted, "before of rule 2 executed?"); } @Test void verifierSupportForErrorCollectorFieldFailsTheTest() { Events tests = executeTestsForClass(VerifierSupportForErrorCollectorTestCase.class); tests.assertStatistics(stats -> stats.started(1).succeeded(0).aborted(0).failed(1)); assertTrue(VerifierSupportForErrorCollectorTestCase.survivedBothErrors, "after of rule 1 executed?"); } private Events executeTestsForClass(Class testClass) { return EngineTestKit.execute("junit-jupiter", request().selectors(selectClass(testClass)).build()).testEvents(); } @EnableRuleMigrationSupport static class EnableRuleMigrationSupportWithBothRuleTypesTestCase { static boolean afterOfRule1WasExecuted = false; static boolean beforeOfRule2WasExecuted = false; static boolean afterOfRule2WasExecuted = false; @Rule public Verifier verifier1 = new Verifier() { @Override protected void verify() { afterOfRule1WasExecuted = true; } }; private ExternalResource resource2 = new ExternalResource() { @Override protected void before() { beforeOfRule2WasExecuted = true; } @Override protected void after() { afterOfRule2WasExecuted = true; } }; @Rule public ExternalResource getResource2() { return resource2; } @Test void beforeMethodOfBothRule2WasExecuted() { assertTrue(beforeOfRule2WasExecuted); } } @ExtendWith(VerifierSupport.class) static class VerifierSupportForErrorCollectorTestCase { static boolean survivedBothErrors = false; @Rule public ErrorCollector collector = new ErrorCollector(); @Test void addingTwoThrowablesToErrorCollectorFailsLate() { collector.addError(new Throwable("first thing went wrong")); collector.addError(new Throwable("second thing went wrong")); survivedBothErrors = true; } } } VerifierSupportForMixedMethodAndFieldRulesTests.java000066400000000000000000000026031455764576500465160ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; @ExtendWith(VerifierSupport.class) public class VerifierSupportForMixedMethodAndFieldRulesTests { private static boolean afterOfRule1WasExecuted = false; private static boolean afterOfRule2WasExecuted = false; @Rule public Verifier verifier1 = new Verifier() { @Override protected void verify() { afterOfRule1WasExecuted = true; } }; private Verifier verifier2 = new Verifier() { @Override protected void verify() { afterOfRule2WasExecuted = true; } }; @Rule public Verifier getVerifier2() { return verifier2; } @Test void testNothing() { //needed to start the test process at all } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { if (!afterOfRule1WasExecuted) fail(); if (!afterOfRule2WasExecuted) fail(); } } WrongExtendWithForVerifierFieldTests.java000066400000000000000000000021221455764576500443500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; @ExtendWith(ExternalResourceSupport.class) public class WrongExtendWithForVerifierFieldTests { private static boolean afterOfRule1WasExecuted = false; @Rule public Verifier verifier1 = new Verifier() { @Override protected void verify() { afterOfRule1WasExecuted = true; } }; @Test void testNothing() { //needed to start the test process at all } @AfterAll static void afterMethodOfRuleWasNotExecuted() { if (afterOfRule1WasExecuted) fail(); } } WrongExtendWithForVerifierMethodTests.java000066400000000000000000000022221455764576500445460ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/java/org/junit/jupiter/migrationsupport/rules/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.migrationsupport.rules; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; @ExtendWith(ExternalResourceSupport.class) public class WrongExtendWithForVerifierMethodTests { private static boolean afterOfRule1WasExecuted = false; private Verifier verifier1 = new Verifier() { @Override protected void verify() { afterOfRule1WasExecuted = true; } }; @Rule public Verifier getVerifier1() { return verifier1; } @Test void testNothing() { //needed to start the test process at all } @AfterAll static void afterMethodsOfBothRulesWereExecuted() { if (afterOfRule1WasExecuted) fail(); } } junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/resources/000077500000000000000000000000001455764576500252445ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-migrationsupport/src/test/resources/log4j2-test.xml000066400000000000000000000006761455764576500300550ustar00rootroot00000000000000 junit5-r5.10.2/junit-jupiter-params/000077500000000000000000000000001455764576500173215ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/LICENSE-univocity-parsers.md000066400000000000000000000221271455764576500244350ustar00rootroot00000000000000Apache License ============== _Version 2.0, January 2004_ _<>_ ### Terms and Conditions for use, reproduction, and distribution #### 1. Definitions “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. #### 2. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. #### 3. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. #### 4. Redistribution You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: * **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and * **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and * **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. #### 5. Submission of Contributions Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. #### 6. Trademarks This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. #### 7. Disclaimer of Warranty Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) 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. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. #### 8. Limitation of Liability In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. #### 9. Accepting Warranty or Additional Liability While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. junit5-r5.10.2/junit-jupiter-params/junit-jupiter-params.gradle.kts000066400000000000000000000027631455764576500254030ustar00rootroot00000000000000plugins { id("junitbuild.kotlin-library-conventions") id("junitbuild.shadow-conventions") id("junitbuild.testing-conventions") } description = "JUnit Jupiter Params" dependencies { api(platform(projects.junitBom)) api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) shadowed(libs.univocity.parsers) testImplementation(projects.junitPlatformTestkit) testImplementation(projects.junitJupiterEngine) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(testFixtures(projects.junitPlatformCommons)) testImplementation(testFixtures(projects.junitJupiterEngine)) compileOnly(kotlin("stdlib")) testImplementation(kotlin("stdlib")) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks { jar { bundle { val version = project.version bnd(""" Require-Capability:\ org.junit.platform.engine;\ filter:='(&(org.junit.platform.engine=junit-jupiter)(version>=${'$'}{version_cleanup;$version})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;$version}})))';\ effective:=active """) } } } tasks { shadowJar { relocate("com.univocity", "org.junit.jupiter.params.shadow.com.univocity") from(projectDir) { include("LICENSE-univocity-parsers.md") into("META-INF") } } compileModule { options.compilerArgs.addAll(listOf( "--add-modules", "univocity.parsers", "--add-reads", "${javaModuleName}=univocity.parsers" )) } } junit5-r5.10.2/junit-jupiter-params/src/000077500000000000000000000000001455764576500201105ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/000077500000000000000000000000001455764576500210345ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/000077500000000000000000000000001455764576500217555ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/000077500000000000000000000000001455764576500225445ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/000077500000000000000000000000001455764576500236755ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/000077500000000000000000000000001455764576500253575ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/000077500000000000000000000000001455764576500266425ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java000066400000000000000000000235071455764576500331500ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; /** * {@code @ParameterizedTest} is used to signal that the annotated method is a * parameterized test method. * *

Such methods must not be {@code private} or {@code static}. * *

Argument Providers and Sources

* *

{@code @ParameterizedTest} methods must specify at least one * {@link org.junit.jupiter.params.provider.ArgumentsProvider ArgumentsProvider} * via {@link org.junit.jupiter.params.provider.ArgumentsSource @ArgumentsSource} * or a corresponding composed annotation (e.g., {@code @ValueSource}, * {@code @CsvSource}, etc.). The provider is responsible for providing a * {@link java.util.stream.Stream Stream} of * {@link org.junit.jupiter.params.provider.Arguments Arguments} that will be * used to invoke the parameterized test method. * *

Formal Parameter List

* *

A {@code @ParameterizedTest} method may declare additional parameters at * the end of the method's parameter list to be resolved by other * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolvers} * (e.g., {@code TestInfo}, {@code TestReporter}, etc). Specifically, a * parameterized test method must declare formal parameters according to the * following rules. * *

    *
  1. Zero or more indexed arguments must be declared first.
  2. *
  3. Zero or more aggregators must be declared next.
  4. *
  5. Zero or more arguments supplied by other {@code ParameterResolver} * implementations must be declared last.
  6. *
* *

In this context, an indexed argument is an argument for a given * index in the {@code Arguments} provided by an {@code ArgumentsProvider} that * is passed as an argument to the parameterized method at the same index in the * method's formal parameter list. An aggregator is any parameter of type * {@link org.junit.jupiter.params.aggregator.ArgumentsAccessor ArgumentsAccessor} * or any parameter annotated with * {@link org.junit.jupiter.params.aggregator.AggregateWith @AggregateWith}. * *

Argument Conversion

* *

Method parameters may be annotated with * {@link org.junit.jupiter.params.converter.ConvertWith @ConvertWith} * or a corresponding composed annotation to specify an explicit * {@link org.junit.jupiter.params.converter.ArgumentConverter ArgumentConverter}. * Otherwise, JUnit Jupiter will attempt to perform an implicit * conversion to the target type automatically (see the User Guide for further * details). * *

Composed Annotations

* *

{@code @ParameterizedTest} may also be used as a meta-annotation in order * to create a custom composed annotation that inherits the semantics * of {@code @ParameterizedTest}. * *

Test Execution Order

* *

By default, test methods will be ordered using an algorithm that is * deterministic but intentionally nonobvious. This ensures that subsequent runs * of a test suite execute test methods in the same order, thereby allowing for * repeatable builds. In this context, a test method is any instance * method that is directly annotated or meta-annotated with {@code @Test}, * {@code @RepeatedTest}, {@code @ParameterizedTest}, {@code @TestFactory}, or * {@code @TestTemplate}. * *

Although true unit tests typically should not rely on the order * in which they are executed, there are times when it is necessary to enforce * a specific test method execution order — for example, when writing * integration tests or functional tests where the sequence of * the tests is important, especially in conjunction with * {@link org.junit.jupiter.api.TestInstance @TestInstance(Lifecycle.PER_CLASS)}. * *

To control the order in which test methods are executed, annotate your * test class or test interface with * {@link org.junit.jupiter.api.TestMethodOrder @TestMethodOrder} and specify * the desired {@link org.junit.jupiter.api.MethodOrderer MethodOrderer} * implementation. * * @since 5.0 * @see org.junit.jupiter.params.provider.Arguments * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.provider.CsvFileSource * @see org.junit.jupiter.params.provider.CsvSource * @see org.junit.jupiter.params.provider.EnumSource * @see org.junit.jupiter.params.provider.MethodSource * @see org.junit.jupiter.params.provider.ValueSource * @see org.junit.jupiter.params.aggregator.ArgumentsAccessor * @see org.junit.jupiter.params.aggregator.AggregateWith * @see org.junit.jupiter.params.converter.ArgumentConverter * @see org.junit.jupiter.params.converter.ConvertWith */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @TestTemplate @ExtendWith(ParameterizedTestExtension.class) @SuppressWarnings("exports") public @interface ParameterizedTest { /** * Placeholder for the {@linkplain org.junit.jupiter.api.TestInfo#getDisplayName * display name} of a {@code @ParameterizedTest} method: {displayName} * * @since 5.3 * @see #name */ String DISPLAY_NAME_PLACEHOLDER = "{displayName}"; /** * Placeholder for the current invocation index of a {@code @ParameterizedTest} * method (1-based): {index} * * @since 5.3 * @see #name */ String INDEX_PLACEHOLDER = "{index}"; /** * Placeholder for the complete, comma-separated arguments list of the * current invocation of a {@code @ParameterizedTest} method: * {arguments} * * @since 5.3 * @see #name */ String ARGUMENTS_PLACEHOLDER = "{arguments}"; /** * Placeholder for the complete, comma-separated named arguments list * of the current invocation of a {@code @ParameterizedTest} method: * {argumentsWithNames} * *

Argument names will be retrieved via the {@link java.lang.reflect.Parameter#getName()} * API if the byte code contains parameter names — for example, if * the code was compiled with the {@code -parameters} command line argument * for {@code javac}. * * @since 5.6 * @see #name */ String ARGUMENTS_WITH_NAMES_PLACEHOLDER = "{argumentsWithNames}"; /** * Default display name pattern for the current invocation of a * {@code @ParameterizedTest} method: {@value} * *

Note that the default pattern does not include the * {@linkplain #DISPLAY_NAME_PLACEHOLDER display name} of the * {@code @ParameterizedTest} method. * * @since 5.3 * @see #name * @see #DISPLAY_NAME_PLACEHOLDER * @see #INDEX_PLACEHOLDER * @see #ARGUMENTS_WITH_NAMES_PLACEHOLDER */ String DEFAULT_DISPLAY_NAME = "[" + INDEX_PLACEHOLDER + "] " + ARGUMENTS_WITH_NAMES_PLACEHOLDER; /** * The display name to be used for individual invocations of the * parameterized test; never blank or consisting solely of whitespace. * *

Defaults to {default_display_name}. * *

If the default display name flag ({default_display_name}) * is not overridden, JUnit will: *

    *
  • Look up the {@value ParameterizedTestExtension#DISPLAY_NAME_PATTERN_KEY} * configuration parameter and use it if available. The configuration * parameter can be supplied via the {@code Launcher} API, build tools (e.g., * Gradle and Maven), a JVM system property, or the JUnit Platform configuration * file (i.e., a file named {@code junit-platform.properties} in the root of * the class path). Consult the User Guide for further information.
  • *
  • Otherwise, the value of the {@link #DEFAULT_DISPLAY_NAME} constant will * be used.
  • *
* *

Supported placeholders

*
    *
  • {@link #DISPLAY_NAME_PLACEHOLDER}
  • *
  • {@link #INDEX_PLACEHOLDER}
  • *
  • {@link #ARGUMENTS_PLACEHOLDER}
  • *
  • {@link #ARGUMENTS_WITH_NAMES_PLACEHOLDER}
  • *
  • {0}, {1}, etc.: an individual argument (0-based)
  • *
* *

For the latter, you may use {@link java.text.MessageFormat} patterns * to customize formatting. Please note that the original arguments are * passed when formatting, regardless of any implicit or explicit argument * conversions. * *

Note that {default_display_name} is a flag rather than a * placeholder. * * @see java.text.MessageFormat */ String name() default "{default_display_name}"; /** * Configure whether all arguments of the parameterized test that implement {@link AutoCloseable} * will be closed after {@link org.junit.jupiter.api.AfterEach @AfterEach} methods * and {@link org.junit.jupiter.api.extension.AfterEachCallback AfterEachCallback} * extensions have been called for the current parameterized test invocation. * *

Defaults to {@code true}. * *

WARNING: if an argument that implements {@code AutoCloseable} * is reused for multiple invocations of the same parameterized test method, * you must set {@code autoCloseArguments} to {@code false} to ensure that * the argument is not closed between invocations. * * @since 5.8 * @see java.lang.AutoCloseable */ @API(status = STABLE, since = "5.10") boolean autoCloseArguments() default true; } ParameterizedTestExtension.java000066400000000000000000000152501455764576500347620ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import java.lang.reflect.Method; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.jupiter.params.support.AnnotationConsumerInitializer; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ class ParameterizedTestExtension implements TestTemplateInvocationContextProvider { private static final String METHOD_CONTEXT_KEY = "context"; static final String ARGUMENT_MAX_LENGTH_KEY = "junit.jupiter.params.displayname.argument.maxlength"; private static final String DEFAULT_DISPLAY_NAME = "{default_display_name}"; static final String DISPLAY_NAME_PATTERN_KEY = "junit.jupiter.params.displayname.default"; @Override public boolean supportsTestTemplate(ExtensionContext context) { if (!context.getTestMethod().isPresent()) { return false; } Method testMethod = context.getTestMethod().get(); if (!isAnnotated(testMethod, ParameterizedTest.class)) { return false; } ParameterizedTestMethodContext methodContext = new ParameterizedTestMethodContext(testMethod); Preconditions.condition(methodContext.hasPotentiallyValidSignature(), () -> String.format( "@ParameterizedTest method [%s] declares formal parameters in an invalid order: " + "argument aggregators must be declared after any indexed arguments " + "and before any arguments resolved by another ParameterResolver.", testMethod.toGenericString())); getStore(context).put(METHOD_CONTEXT_KEY, methodContext); return true; } @Override public Stream provideTestTemplateInvocationContexts( ExtensionContext extensionContext) { Method templateMethod = extensionContext.getRequiredTestMethod(); String displayName = extensionContext.getDisplayName(); ParameterizedTestMethodContext methodContext = getStore(extensionContext)// .get(METHOD_CONTEXT_KEY, ParameterizedTestMethodContext.class); int argumentMaxLength = extensionContext.getConfigurationParameter(ARGUMENT_MAX_LENGTH_KEY, Integer::parseInt).orElse(512); ParameterizedTestNameFormatter formatter = createNameFormatter(extensionContext, templateMethod, methodContext, displayName, argumentMaxLength); AtomicLong invocationCount = new AtomicLong(0); // @formatter:off return findRepeatableAnnotations(templateMethod, ArgumentsSource.class) .stream() .map(ArgumentsSource::value) .map(this::instantiateArgumentsProvider) .map(provider -> AnnotationConsumerInitializer.initialize(templateMethod, provider)) .flatMap(provider -> arguments(provider, extensionContext)) .map(Arguments::get) .map(arguments -> consumedArguments(arguments, methodContext)) .map(arguments -> { invocationCount.incrementAndGet(); return createInvocationContext(formatter, methodContext, arguments, invocationCount.intValue()); }) .onClose(() -> Preconditions.condition(invocationCount.get() > 0, "Configuration error: You must configure at least one set of arguments for this @ParameterizedTest")); // @formatter:on } @SuppressWarnings("ConstantConditions") private ArgumentsProvider instantiateArgumentsProvider(Class clazz) { try { return ReflectionUtils.newInstance(clazz); } catch (Exception ex) { if (ex instanceof NoSuchMethodException) { String message = String.format("Failed to find a no-argument constructor for ArgumentsProvider [%s]. " + "Please ensure that a no-argument constructor exists and " + "that the class is either a top-level class or a static nested class", clazz.getName()); throw new JUnitException(message, ex); } throw ex; } } private ExtensionContext.Store getStore(ExtensionContext context) { return context.getStore(Namespace.create(ParameterizedTestExtension.class, context.getRequiredTestMethod())); } private TestTemplateInvocationContext createInvocationContext(ParameterizedTestNameFormatter formatter, ParameterizedTestMethodContext methodContext, Object[] arguments, int invocationIndex) { return new ParameterizedTestInvocationContext(formatter, methodContext, arguments, invocationIndex); } private ParameterizedTestNameFormatter createNameFormatter(ExtensionContext extensionContext, Method templateMethod, ParameterizedTestMethodContext methodContext, String displayName, int argumentMaxLength) { ParameterizedTest parameterizedTest = findAnnotation(templateMethod, ParameterizedTest.class).get(); String pattern = parameterizedTest.name().equals(DEFAULT_DISPLAY_NAME) ? extensionContext.getConfigurationParameter(DISPLAY_NAME_PATTERN_KEY).orElse( ParameterizedTest.DEFAULT_DISPLAY_NAME) : parameterizedTest.name(); pattern = Preconditions.notBlank(pattern.trim(), () -> String.format( "Configuration error: @ParameterizedTest on method [%s] must be declared with a non-empty name.", templateMethod)); return new ParameterizedTestNameFormatter(pattern, displayName, methodContext, argumentMaxLength); } protected static Stream arguments(ArgumentsProvider provider, ExtensionContext context) { try { return provider.provideArguments(context); } catch (Exception e) { throw ExceptionUtils.throwAsUncheckedException(e); } } private Object[] consumedArguments(Object[] arguments, ParameterizedTestMethodContext methodContext) { if (methodContext.hasAggregator()) { return arguments; } int parameterCount = methodContext.getParameterCount(); return arguments.length > parameterCount ? Arrays.copyOf(arguments, parameterCount) : arguments; } } ParameterizedTestInvocationContext.java000066400000000000000000000027161455764576500364670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static java.util.Collections.singletonList; import java.util.List; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; /** * @since 5.0 */ class ParameterizedTestInvocationContext implements TestTemplateInvocationContext { private final ParameterizedTestNameFormatter formatter; private final ParameterizedTestMethodContext methodContext; private final Object[] arguments; private final int invocationIndex; ParameterizedTestInvocationContext(ParameterizedTestNameFormatter formatter, ParameterizedTestMethodContext methodContext, Object[] arguments, int invocationIndex) { this.formatter = formatter; this.methodContext = methodContext; this.arguments = arguments; this.invocationIndex = invocationIndex; } @Override public String getDisplayName(int invocationIndex) { return this.formatter.format(invocationIndex, this.arguments); } @Override public List getAdditionalExtensions() { return singletonList( new ParameterizedTestParameterResolver(this.methodContext, this.arguments, this.invocationIndex)); } } ParameterizedTestMethodContext.java000066400000000000000000000221711455764576500355730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.junit.jupiter.params.ParameterizedTestMethodContext.ResolverType.AGGREGATOR; import static org.junit.jupiter.params.ParameterizedTestMethodContext.ResolverType.CONVERTER; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.params.aggregator.AggregateWith; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.aggregator.ArgumentsAggregator; import org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor; import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.converter.DefaultArgumentConverter; import org.junit.jupiter.params.support.AnnotationConsumerInitializer; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; /** * Encapsulates access to the parameters of a parameterized test method and * caches the converters and aggregators used to resolve them. * * @since 5.3 */ class ParameterizedTestMethodContext { private final Parameter[] parameters; private final Resolver[] resolvers; private final List resolverTypes; ParameterizedTestMethodContext(Method testMethod) { this.parameters = testMethod.getParameters(); this.resolvers = new Resolver[this.parameters.length]; this.resolverTypes = new ArrayList<>(this.parameters.length); for (Parameter parameter : this.parameters) { this.resolverTypes.add(isAggregator(parameter) ? AGGREGATOR : CONVERTER); } } /** * Determine if the supplied {@link Parameter} is an aggregator (i.e., of * type {@link ArgumentsAccessor} or annotated with {@link AggregateWith}). * * @return {@code true} if the parameter is an aggregator */ private static boolean isAggregator(Parameter parameter) { return ArgumentsAccessor.class.isAssignableFrom(parameter.getType()) || isAnnotated(parameter, AggregateWith.class); } /** * Determine if the {@link Method} represented by this context has a * potentially valid signature (i.e., formal parameter * declarations) with regard to aggregators. * *

This method takes a best-effort approach at enforcing the following * policy for parameterized test methods that accept aggregators as arguments. * *

    *
  1. zero or more indexed arguments come first.
  2. *
  3. zero or more aggregators come next.
  4. *
  5. zero or more arguments supplied by other {@code ParameterResolver} * implementations come last.
  6. *
* * @return {@code true} if the method has a potentially valid signature */ boolean hasPotentiallyValidSignature() { int indexOfPreviousAggregator = -1; for (int i = 0; i < getParameterCount(); i++) { if (isAggregator(i)) { if ((indexOfPreviousAggregator != -1) && (i != indexOfPreviousAggregator + 1)) { return false; } indexOfPreviousAggregator = i; } } return true; } /** * Get the number of parameters of the {@link Method} represented by this * context. */ int getParameterCount() { return parameters.length; } /** * Get the name of the {@link Parameter} with the supplied index, if * it is present and declared before the aggregators. * * @return an {@code Optional} containing the name of the parameter */ Optional getParameterName(int parameterIndex) { if (parameterIndex >= getParameterCount()) { return Optional.empty(); } Parameter parameter = this.parameters[parameterIndex]; if (!parameter.isNamePresent()) { return Optional.empty(); } if (hasAggregator() && parameterIndex >= indexOfFirstAggregator()) { return Optional.empty(); } return Optional.of(parameter.getName()); } /** * Determine if the {@link Method} represented by this context declares at * least one {@link Parameter} that is an * {@linkplain #isAggregator aggregator}. * * @return {@code true} if the method has an aggregator */ boolean hasAggregator() { return resolverTypes.contains(AGGREGATOR); } /** * Determine if the {@link Parameter} with the supplied index is an * aggregator (i.e., of type {@link ArgumentsAccessor} or annotated with * {@link AggregateWith}). * * @return {@code true} if the parameter is an aggregator */ boolean isAggregator(int parameterIndex) { return resolverTypes.get(parameterIndex) == AGGREGATOR; } /** * Find the index of the first {@linkplain #isAggregator aggregator} * {@link Parameter} in the {@link Method} represented by this context. * * @return the index of the first aggregator, or {@code -1} if not found */ int indexOfFirstAggregator() { return resolverTypes.indexOf(AGGREGATOR); } /** * Resolve the parameter for the supplied context using the supplied * arguments. */ Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) { return getResolver(parameterContext).resolve(parameterContext, arguments, invocationIndex); } private Resolver getResolver(ParameterContext parameterContext) { int index = parameterContext.getIndex(); if (resolvers[index] == null) { resolvers[index] = resolverTypes.get(index).createResolver(parameterContext); } return resolvers[index]; } enum ResolverType { CONVERTER { @Override Resolver createResolver(ParameterContext parameterContext) { try { // @formatter:off return AnnotationUtils.findAnnotation(parameterContext.getParameter(), ConvertWith.class) .map(ConvertWith::value) .map(clazz -> (ArgumentConverter) ReflectionUtils.newInstance(clazz)) .map(converter -> AnnotationConsumerInitializer.initialize(parameterContext.getParameter(), converter)) .map(Converter::new) .orElse(Converter.DEFAULT); } // @formatter:on catch (Exception ex) { throw parameterResolutionException("Error creating ArgumentConverter", ex, parameterContext); } } }, AGGREGATOR { @Override Resolver createResolver(ParameterContext parameterContext) { try { // @formatter:off return AnnotationUtils.findAnnotation(parameterContext.getParameter(), AggregateWith.class) .map(AggregateWith::value) .map(clazz -> (ArgumentsAggregator) ReflectionSupport.newInstance(clazz)) .map(Aggregator::new) .orElse(Aggregator.DEFAULT); } // @formatter:on catch (Exception ex) { throw parameterResolutionException("Error creating ArgumentsAggregator", ex, parameterContext); } } }; abstract Resolver createResolver(ParameterContext parameterContext); } interface Resolver { Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex); } static class Converter implements Resolver { private static final Converter DEFAULT = new Converter(DefaultArgumentConverter.INSTANCE); private final ArgumentConverter argumentConverter; Converter(ArgumentConverter argumentConverter) { this.argumentConverter = argumentConverter; } @Override public Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) { Object argument = arguments[parameterContext.getIndex()]; try { return this.argumentConverter.convert(argument, parameterContext); } catch (Exception ex) { throw parameterResolutionException("Error converting parameter", ex, parameterContext); } } } static class Aggregator implements Resolver { private static final Aggregator DEFAULT = new Aggregator((accessor, context) -> accessor); private final ArgumentsAggregator argumentsAggregator; Aggregator(ArgumentsAggregator argumentsAggregator) { this.argumentsAggregator = argumentsAggregator; } @Override public Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) { ArgumentsAccessor accessor = new DefaultArgumentsAccessor(parameterContext, invocationIndex, arguments); try { return this.argumentsAggregator.aggregateArguments(accessor, parameterContext); } catch (Exception ex) { throw parameterResolutionException("Error aggregating arguments for parameter", ex, parameterContext); } } } private static ParameterResolutionException parameterResolutionException(String message, Exception cause, ParameterContext parameterContext) { String fullMessage = message + " at index " + parameterContext.getIndex(); if (StringUtils.isNotBlank(cause.getMessage())) { fullMessage += ": " + cause.getMessage(); } return new ParameterResolutionException(fullMessage, cause); } } ParameterizedTestNameFormatter.java000066400000000000000000000104371455764576500355540ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.params.ParameterizedTest.ARGUMENTS_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.ARGUMENTS_WITH_NAMES_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.DISPLAY_NAME_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.INDEX_PLACEHOLDER; import java.text.Format; import java.text.MessageFormat; import java.util.Arrays; import java.util.stream.IntStream; import org.junit.jupiter.api.Named; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.StringUtils; /** * @since 5.0 */ class ParameterizedTestNameFormatter { private static final char ELLIPSIS = '\u2026'; private static final String TEMPORARY_DISPLAY_NAME_PLACEHOLDER = "~~~JUNIT_DISPLAY_NAME~~~"; private final String pattern; private final String displayName; private final ParameterizedTestMethodContext methodContext; private final int argumentMaxLength; ParameterizedTestNameFormatter(String pattern, String displayName, ParameterizedTestMethodContext methodContext, int argumentMaxLength) { this.pattern = pattern; this.displayName = displayName; this.methodContext = methodContext; this.argumentMaxLength = argumentMaxLength; } String format(int invocationIndex, Object... arguments) { try { return formatSafely(invocationIndex, arguments); } catch (Exception ex) { String message = "The display name pattern defined for the parameterized test is invalid. " + "See nested exception for further details."; throw new JUnitException(message, ex); } } private String formatSafely(int invocationIndex, Object[] arguments) { Object[] namedArguments = extractNamedArguments(arguments); String pattern = prepareMessageFormatPattern(invocationIndex, namedArguments); MessageFormat format = new MessageFormat(pattern); Object[] humanReadableArguments = makeReadable(format, namedArguments); String formatted = format.format(humanReadableArguments); return formatted.replace(TEMPORARY_DISPLAY_NAME_PLACEHOLDER, this.displayName); } private Object[] extractNamedArguments(Object[] arguments) { return Arrays.stream(arguments) // .map(argument -> argument instanceof Named ? ((Named) argument).getName() : argument) // .toArray(); } private String prepareMessageFormatPattern(int invocationIndex, Object[] arguments) { String result = pattern// .replace(DISPLAY_NAME_PLACEHOLDER, TEMPORARY_DISPLAY_NAME_PLACEHOLDER)// .replace(INDEX_PLACEHOLDER, String.valueOf(invocationIndex)); if (result.contains(ARGUMENTS_WITH_NAMES_PLACEHOLDER)) { result = result.replace(ARGUMENTS_WITH_NAMES_PLACEHOLDER, argumentsWithNamesPattern(arguments)); } if (result.contains(ARGUMENTS_PLACEHOLDER)) { result = result.replace(ARGUMENTS_PLACEHOLDER, argumentsPattern(arguments)); } return result; } private String argumentsWithNamesPattern(Object[] arguments) { return IntStream.range(0, arguments.length) // .mapToObj(index -> methodContext.getParameterName(index).map(name -> name + "=").orElse("") + "{" + index + "}") // .collect(joining(", ")); } private String argumentsPattern(Object[] arguments) { return IntStream.range(0, arguments.length) // .mapToObj(index -> "{" + index + "}") // .collect(joining(", ")); } private Object[] makeReadable(MessageFormat format, Object[] arguments) { Format[] formats = format.getFormatsByArgumentIndex(); Object[] result = Arrays.copyOf(arguments, Math.min(arguments.length, formats.length), Object[].class); for (int i = 0; i < result.length; i++) { if (formats[i] == null) { result[i] = truncateIfExceedsMaxLength(StringUtils.nullSafeToString(arguments[i])); } } return result; } private String truncateIfExceedsMaxLength(String argument) { if (argument != null && argument.length() > argumentMaxLength) { return argument.substring(0, argumentMaxLength - 1) + ELLIPSIS; } return argument; } } ParameterizedTestParameterResolver.java000066400000000000000000000077551455764576500364630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.platform.commons.util.AnnotationUtils; /** * @since 5.0 */ class ParameterizedTestParameterResolver implements ParameterResolver, AfterTestExecutionCallback { private static final Namespace NAMESPACE = Namespace.create(ParameterizedTestParameterResolver.class); private final ParameterizedTestMethodContext methodContext; private final Object[] arguments; private final int invocationIndex; ParameterizedTestParameterResolver(ParameterizedTestMethodContext methodContext, Object[] arguments, int invocationIndex) { this.methodContext = methodContext; this.arguments = arguments; this.invocationIndex = invocationIndex; } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Executable declaringExecutable = parameterContext.getDeclaringExecutable(); Method testMethod = extensionContext.getTestMethod().orElse(null); int parameterIndex = parameterContext.getIndex(); // Not a @ParameterizedTest method? if (!declaringExecutable.equals(testMethod)) { return false; } // Current parameter is an aggregator? if (this.methodContext.isAggregator(parameterIndex)) { return true; } // Ensure that the current parameter is declared before aggregators. // Otherwise, a different ParameterResolver should handle it. if (this.methodContext.hasAggregator()) { return parameterIndex < this.methodContext.indexOfFirstAggregator(); } // Else fallback to behavior for parameterized test methods without aggregators. return parameterIndex < this.arguments.length; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return this.methodContext.resolve(parameterContext, extractPayloads(this.arguments), this.invocationIndex); } /** * @since 5.8 */ @Override public void afterTestExecution(ExtensionContext context) { ParameterizedTest parameterizedTest = AnnotationUtils.findAnnotation(context.getRequiredTestMethod(), ParameterizedTest.class).get(); if (!parameterizedTest.autoCloseArguments()) { return; } Store store = context.getStore(NAMESPACE); AtomicInteger argumentIndex = new AtomicInteger(); Arrays.stream(this.arguments) // .filter(AutoCloseable.class::isInstance) // .map(AutoCloseable.class::cast) // .map(CloseableArgument::new) // .forEach(closeable -> store.put("closeableArgument#" + argumentIndex.incrementAndGet(), closeable)); } private static class CloseableArgument implements Store.CloseableResource { private final AutoCloseable autoCloseable; CloseableArgument(AutoCloseable autoCloseable) { this.autoCloseable = autoCloseable; } @Override public void close() throws Throwable { this.autoCloseable.close(); } } private Object[] extractPayloads(Object[] arguments) { return Arrays.stream(arguments) // .map(argument -> { if (argument instanceof Named) { return ((Named) argument).getPayload(); } return argument; }) // .toArray(); } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/000077500000000000000000000000001455764576500307645ustar00rootroot00000000000000AggregateWith.java000066400000000000000000000030001455764576500342630ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @AggregateWith} is an annotation that allows one to specify an * {@link ArgumentsAggregator}. * *

This annotation may be applied to a parameter of a * {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest} method * in order for an aggregated value to be resolved for the annotated parameter * when the test method is invoked. * *

{@code @AggregateWith} may also be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @AggregateWith}. * * @since 5.2 * @see ArgumentsAggregator * @see org.junit.jupiter.params.ParameterizedTest */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.PARAMETER, ElementType.ANNOTATION_TYPE }) @Documented @API(status = STABLE, since = "5.7") public @interface AggregateWith { Class value(); } ArgumentAccessException.java000066400000000000000000000020041455764576500363270ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * {@code ArgumentAccessException} is an exception thrown by an * {@link ArgumentsAccessor} if an error occurs while accessing * or converting an argument. * * @since 5.2 * @see ArgumentsAccessor */ @API(status = STABLE, since = "5.7") public class ArgumentAccessException extends JUnitException { private static final long serialVersionUID = 1L; public ArgumentAccessException(String message) { super(message); } public ArgumentAccessException(String message, Throwable cause) { super(message, cause); } } ArgumentsAccessor.java000066400000000000000000000162741455764576500352120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import org.apiguardian.api.API; /** * {@code ArgumentsAccessor} defines the public API for accessing arguments provided * by an {@link org.junit.jupiter.params.provider.ArgumentsProvider ArgumentsProvider} * for a single invocation of a * {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest} method. * *

Specifically, an {@code ArgumentsAccessor} aggregates a set of * arguments for a given invocation of a parameterized test and provides convenience * methods for accessing those arguments in a type-safe manner with support for * automatic type conversion. * *

An instance of {@code ArgumentsAccessor} will be automatically supplied * for any parameter of type {@code ArgumentsAccessor} in a parameterized test. * In addition, {@link ArgumentsAggregator} implementations are given access to * an {@code ArgumentsAccessor}. * *

This interface is not intended to be implemented by clients. * *

Additional Kotlin arguments accessors can be * found as extension functions in the {@link org.junit.jupiter.params.aggregator} * package. * * @since 5.2 * @see ArgumentsAggregator * @see org.junit.jupiter.params.ParameterizedTest */ @API(status = STABLE, since = "5.7") public interface ArgumentsAccessor { /** * Get the value of the argument at the given index as an {@link Object}. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} */ Object get(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as an instance of the * required type. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @param requiredType the required type of the value; never {@code null} * @return the value at the given index, potentially {@code null} */ T get(int index, Class requiredType) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Character}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Character getCharacter(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Boolean}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Boolean getBoolean(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Byte}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Byte getByte(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Short}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Short getShort(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Integer}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Integer getInteger(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Long}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Long getLong(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Float}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Float getFloat(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Double}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ Double getDouble(int index) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link String}, * performing automatic type conversion as necessary. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ String getString(int index) throws ArgumentAccessException; /** * Get the number of arguments in this accessor. */ int size(); /** * Get all arguments in this accessor as an array. */ Object[] toArray(); /** * Get all arguments in this accessor as an immutable list. */ List toList(); /** * Get the index of the current test invocation. */ int getInvocationIndex(); } ArgumentsAggregationException.java000066400000000000000000000020241455764576500375420ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * {@code ArgumentsAggregationException} is an exception thrown by an * {@link ArgumentsAggregator} when an error occurs while aggregating * arguments. * * @since 5.2 * @see ArgumentsAggregator */ @API(status = STABLE, since = "5.7") public class ArgumentsAggregationException extends JUnitException { private static final long serialVersionUID = 1L; public ArgumentsAggregationException(String message) { super(message); } public ArgumentsAggregationException(String message, Throwable cause) { super(message, cause); } } ArgumentsAggregator.java000066400000000000000000000047031455764576500355240ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; /** * {@code ArgumentsAggregator} is an abstraction for the aggregation of arguments * provided by an {@link org.junit.jupiter.params.provider.ArgumentsProvider * ArgumentsProvider} for a single invocation of a * {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest} method * into a single object. * *

An {@code ArgumentsAggregator} is applied to a method parameter of a * {@code @ParameterizedTest} method via the {@link AggregateWith @AggregateWith} * annotation. * *

The result of the aggregation will be passed as an argument to the * {@code @ParameterizedTest} method for the annotated parameter. * *

A common use case is the aggregation of multiple columns from a single line * in a CSV file into a domain object such as a {@code Person}, {@code Address}, * {@code Order}, etc. * *

Implementations must provide a no-args constructor and should not make any * assumptions regarding when they are instantiated or how often they are called. * Since instances may potentially be cached and called from different threads, * they should be thread-safe and designed to be used as singletons. * * @since 5.2 * @see AggregateWith * @see ArgumentsAccessor * @see org.junit.jupiter.params.ParameterizedTest */ @API(status = STABLE, since = "5.7") public interface ArgumentsAggregator { /** * Aggregate the arguments contained in the supplied {@code accessor} into a * single object. * * @param accessor an {@link ArgumentsAccessor} containing the arguments to be * aggregated; never {@code null} * @param context the parameter context where the aggregated result is to be * supplied; never {@code null} * @return the aggregated result; may be {@code null} but only if the target * type is a reference type * @throws ArgumentsAggregationException if an error occurs during the * aggregation */ Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException; } DefaultArgumentsAccessor.java000066400000000000000000000073641455764576500365170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.converter.DefaultArgumentConverter; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; /** * Default implementation of the {@link ArgumentsAccessor} API. * *

Delegates conversion to {@link DefaultArgumentConverter}. * * @since 5.2 * @see ArgumentsAccessor * @see DefaultArgumentConverter * @see org.junit.jupiter.params.ParameterizedTest */ @API(status = INTERNAL, since = "5.2") public class DefaultArgumentsAccessor implements ArgumentsAccessor { private final ParameterContext parameterContext; private final int invocationIndex; private final Object[] arguments; public DefaultArgumentsAccessor(ParameterContext parameterContext, int invocationIndex, Object... arguments) { Preconditions.notNull(parameterContext, "ParameterContext must not be null"); Preconditions.condition(invocationIndex >= 1, () -> "invocation index must be >= 1"); Preconditions.notNull(arguments, "Arguments array must not be null"); this.parameterContext = parameterContext; this.invocationIndex = invocationIndex; this.arguments = arguments; } @Override public Object get(int index) { Preconditions.condition(index >= 0 && index < this.arguments.length, () -> format("index must be >= 0 and < %d", this.arguments.length)); return this.arguments[index]; } @Override public T get(int index, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); Object value = get(index); try { Object convertedValue = DefaultArgumentConverter.INSTANCE.convert(value, requiredType, this.parameterContext); return requiredType.cast(convertedValue); } catch (Exception ex) { String message = format( "Argument at index [%d] with value [%s] and type [%s] could not be converted or cast to type [%s].", index, value, ClassUtils.nullSafeToString(value == null ? null : value.getClass()), requiredType.getName()); throw new ArgumentAccessException(message, ex); } } @Override public Character getCharacter(int index) { return get(index, Character.class); } @Override public Boolean getBoolean(int index) { return get(index, Boolean.class); } @Override public Byte getByte(int index) { return get(index, Byte.class); } @Override public Short getShort(int index) { return get(index, Short.class); } @Override public Integer getInteger(int index) { return get(index, Integer.class); } @Override public Long getLong(int index) { return get(index, Long.class); } @Override public Float getFloat(int index) { return get(index, Float.class); } @Override public Double getDouble(int index) { return get(index, Double.class); } @Override public String getString(int index) { return get(index, String.class); } @Override public int size() { return this.arguments.length; } @Override public Object[] toArray() { return Arrays.copyOf(this.arguments, this.arguments.length); } @Override public List toList() { return Collections.unmodifiableList(Arrays.asList(this.arguments)); } @Override public int getInvocationIndex() { return this.invocationIndex; } } package-info.java000066400000000000000000000004361455764576500340770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/** * The {@link org.junit.jupiter.params.aggregator.ArgumentsAggregator} and * {@link org.junit.jupiter.params.aggregator.ArgumentsAccessor} interfaces and the * {@link org.junit.jupiter.params.aggregator.AggregateWith} annotation. */ package org.junit.jupiter.params.aggregator; junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/000077500000000000000000000000001455764576500306515ustar00rootroot00000000000000AnnotationBasedArgumentConverter.java000066400000000000000000000043661455764576500401120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Annotation; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.util.Preconditions; /** * {@code AnnotationBasedArgumentConverter} is an abstract base class for * {@link ArgumentConverter} implementations that also need to consume an * annotation in order to perform the conversion. * * @since 5.10 * @see ArgumentConverter * @see AnnotationConsumer * @see SimpleArgumentConverter */ @API(status = EXPERIMENTAL, since = "5.10") public abstract class AnnotationBasedArgumentConverter implements ArgumentConverter, AnnotationConsumer { public AnnotationBasedArgumentConverter() { } private A annotation; @Override public final void accept(A annotation) { Preconditions.notNull(annotation, "annotation must not be null"); this.annotation = annotation; } @Override public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return convert(source, context.getParameter().getType(), this.annotation); } /** * Convert the supplied {@code source} object into the supplied {@code targetType}, * based on metadata in the provided annotation. * * @param source the source object to convert; may be {@code null} * @param targetType the target type the source object should be converted * into; never {@code null} * @param annotation the annotation to process; never {@code null} * @return the converted object; may be {@code null} but only if the target * type is a reference type * @throws ArgumentConversionException in case an error occurs during the * conversion */ protected abstract Object convert(Object source, Class targetType, A annotation) throws ArgumentConversionException; } ArgumentConversionException.java000066400000000000000000000020411455764576500371410ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * {@code ArgumentConversionException} is an exception that can occur when an * object is converted to another object by an implementation of an * {@link ArgumentConverter}. * * @since 5.0 * @see ArgumentConverter */ @API(status = STABLE, since = "5.7") public class ArgumentConversionException extends JUnitException { private static final long serialVersionUID = 1L; public ArgumentConversionException(String message) { super(message); } public ArgumentConversionException(String message, Throwable cause) { super(message, cause); } } ArgumentConverter.java000066400000000000000000000050111455764576500351040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; /** * {@code ArgumentConverter} is an abstraction that allows an input object to * be converted to an instance of a different class. * *

Such an {@code ArgumentConverter} is applied to the method parameter * of a {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest} * method with the help of a * {@link org.junit.jupiter.params.converter.ConvertWith @ConvertWith} annotation. * *

Implementations must provide a no-args constructor and should not make any * assumptions regarding when they are instantiated or how often they are called. * Since instances may potentially be cached and called from different threads, * they should be thread-safe and designed to be used as singletons. * *

Extend {@link SimpleArgumentConverter} if your implementation only needs * to know the target type and does not need access to the {@link ParameterContext} * to perform the conversion. * *

Extend {@link TypedArgumentConverter} if your implementation always converts * from a given source type into a given target type and does not need access to * the {@link ParameterContext} to perform the conversion. * * @since 5.0 * @see SimpleArgumentConverter * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.converter.ConvertWith * @see org.junit.jupiter.params.support.AnnotationConsumer * @see SimpleArgumentConverter * @see TypedArgumentConverter */ @API(status = STABLE, since = "5.7") public interface ArgumentConverter { /** * Convert the supplied {@code source} object according to the supplied * {@code context}. * * @param source the source object to convert; may be {@code null} * @param context the parameter context where the converted object will be * used; never {@code null} * @return the converted object; may be {@code null} but only if the target * type is a reference type * @throws ArgumentConversionException if an error occurs during the * conversion */ Object convert(Object source, ParameterContext context) throws ArgumentConversionException; } ConvertWith.java000066400000000000000000000025711455764576500337160ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ConvertWith} is an annotation that allows one to specify an explicit * {@link ArgumentConverter}. *

This annotation may be applied to parameters of * {@link org.junit.jupiter.params.ParameterizedTest @ParameterizedTest} methods * which need to have their {@code Arguments} converted before consuming them. * * @since 5.0 * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.converter.ArgumentConverter */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") public @interface ConvertWith { /** * The type of {@link ArgumentConverter} to use. */ Class value(); } DefaultArgumentConverter.java000066400000000000000000000102721455764576500364160ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; import java.io.File; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.Currency; import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.UUID; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code DefaultArgumentConverter} is the default implementation of the * {@link ArgumentConverter} API. * *

The {@code DefaultArgumentConverter} is able to convert from strings to a * number of primitive types and their corresponding wrapper types (Byte, Short, * Integer, Long, Float, and Double), date and time types from the * {@code java.time} package, and some additional common Java types such as * {@link File}, {@link BigDecimal}, {@link BigInteger}, {@link Currency}, * {@link Locale}, {@link URI}, {@link URL}, {@link UUID}, etc. * *

If the source and target types are identical the source object will not * be modified. * * @since 5.0 * @see org.junit.jupiter.params.converter.ArgumentConverter */ @API(status = INTERNAL, since = "5.0") public class DefaultArgumentConverter implements ArgumentConverter { public static final DefaultArgumentConverter INSTANCE = new DefaultArgumentConverter(); private static final List stringToObjectConverters = unmodifiableList(asList( // new StringToBooleanConverter(), // new StringToCharacterConverter(), // new StringToNumberConverter(), // new StringToClassConverter(), // new StringToEnumConverter(), // new StringToJavaTimeConverter(), // new StringToCommonJavaTypesConverter(), // new FallbackStringToObjectConverter() // )); private DefaultArgumentConverter() { // nothing to initialize } @Override public final Object convert(Object source, ParameterContext context) { Class targetType = context.getParameter().getType(); return convert(source, targetType, context); } public final Object convert(Object source, Class targetType, ParameterContext context) { if (source == null) { if (targetType.isPrimitive()) { throw new ArgumentConversionException( "Cannot convert null to primitive value of type " + targetType.getTypeName()); } return null; } if (ReflectionUtils.isAssignableTo(source, targetType)) { return source; } if (source instanceof String) { Class targetTypeToUse = toWrapperType(targetType); Optional converter = stringToObjectConverters.stream().filter( candidate -> candidate.canConvert(targetTypeToUse)).findFirst(); if (converter.isPresent()) { Class declaringClass = context.getDeclaringExecutable().getDeclaringClass(); ClassLoader classLoader = ClassLoaderUtils.getClassLoader(declaringClass); try { return converter.get().convert((String) source, targetTypeToUse, classLoader); } catch (Exception ex) { if (ex instanceof ArgumentConversionException) { // simply rethrow it throw (ArgumentConversionException) ex; } // else throw new ArgumentConversionException( "Failed to convert String \"" + source + "\" to type " + targetType.getTypeName(), ex); } } } throw new ArgumentConversionException( String.format("No built-in converter for source type %s and target type %s", source.getClass().getTypeName(), targetType.getTypeName())); } private static Class toWrapperType(Class targetType) { Class wrapperType = getWrapperType(targetType); return wrapperType != null ? wrapperType : targetType; } } FallbackStringToObjectConverter.java000066400000000000000000000134421455764576500376510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.findConstructors; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.commons.util.ReflectionUtils.invokeMethod; import static org.junit.platform.commons.util.ReflectionUtils.isNotPrivate; import static org.junit.platform.commons.util.ReflectionUtils.isNotStatic; import static org.junit.platform.commons.util.ReflectionUtils.newInstance; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import org.junit.platform.commons.util.Preconditions; /** * {@code FallbackStringToObjectConverter} is a {@link StringToObjectConverter} * that provides a fallback conversion strategy for converting from a * {@link String} to a given target type by invoking a static factory method * or factory constructor defined in the target type. * *

Search Algorithm

* *
    *
  1. Search for a single, non-private static factory method in the target * type that converts from a String to the target type. Use the factory method * if present.
  2. *
  3. Search for a single, non-private constructor in the target type that * accepts a String. Use the constructor if present.
  4. *
* *

If multiple suitable factory methods are discovered they will be ignored. * If neither a single factory method nor a single constructor is found, this * converter acts as a no-op. * * @since 5.1 * @see DefaultArgumentConverter */ class FallbackStringToObjectConverter implements StringToObjectConverter { /** * Implementation of the NULL Object Pattern. */ private static final Function NULL_EXECUTABLE = source -> source; /** * Cache for factory methods and factory constructors. * *

Searches that do not find a factory method or constructor are tracked * by the presence of a {@link #NULL_EXECUTABLE} object stored in the map. * This prevents the framework from repeatedly searching for things which * are already known not to exist. */ private static final ConcurrentHashMap, Function> factoryExecutableCache // = new ConcurrentHashMap<>(64); @Override public boolean canConvert(Class targetType) { return findFactoryExecutable(targetType) != NULL_EXECUTABLE; } @Override public Object convert(String source, Class targetType) throws Exception { Function executable = findFactoryExecutable(targetType); Preconditions.condition(executable != NULL_EXECUTABLE, "Illegal state: convert() must not be called if canConvert() returned false"); return executable.apply(source); } private static Function findFactoryExecutable(Class targetType) { return factoryExecutableCache.computeIfAbsent(targetType, type -> { Method factoryMethod = findFactoryMethod(type); if (factoryMethod != null) { return source -> invokeMethod(factoryMethod, null, source); } Constructor constructor = findFactoryConstructor(type); if (constructor != null) { return source -> newInstance(constructor, source); } return NULL_EXECUTABLE; }); } private static Method findFactoryMethod(Class targetType) { List factoryMethods = findMethods(targetType, new IsFactoryMethod(targetType), BOTTOM_UP); if (factoryMethods.size() == 1) { return factoryMethods.get(0); } return null; } private static Constructor findFactoryConstructor(Class targetType) { List> constructors = findConstructors(targetType, new IsFactoryConstructor(targetType)); if (constructors.size() == 1) { return constructors.get(0); } return null; } /** * {@link Predicate} that determines if the {@link Method} supplied to * {@link #test(Method)} is a non-private static factory method for the * supplied {@link #targetType}. */ static class IsFactoryMethod implements Predicate { private final Class targetType; IsFactoryMethod(Class targetType) { this.targetType = targetType; } @Override public boolean test(Method method) { // Please do not collapse the following into a single statement. if (!method.getReturnType().equals(this.targetType)) { return false; } if (isNotStatic(method)) { return false; } return isNotPrivateAndAcceptsSingleStringArgument(method); } } /** * {@link Predicate} that determines if the {@link Constructor} supplied to * {@link #test(Constructor)} is a non-private factory constructor for the * supplied {@link #targetType}. */ static class IsFactoryConstructor implements Predicate> { private final Class targetType; IsFactoryConstructor(Class targetType) { this.targetType = targetType; } @Override public boolean test(Constructor constructor) { // Please do not collapse the following into a single statement. if (!constructor.getDeclaringClass().equals(this.targetType)) { return false; } return isNotPrivateAndAcceptsSingleStringArgument(constructor); } } private static boolean isNotPrivateAndAcceptsSingleStringArgument(Executable executable) { return isNotPrivate(executable) // && (executable.getParameterCount() == 1) // && (executable.getParameterTypes()[0] == String.class); } } JavaTimeArgumentConverter.java000066400000000000000000000046261455764576500365400ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.Year; import java.time.YearMonth; import java.time.ZonedDateTime; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalQuery; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; /** * @since 5.0 */ class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter { private static final Map, TemporalQuery> TEMPORAL_QUERIES; static { Map, TemporalQuery> queries = new LinkedHashMap<>(); queries.put(ChronoLocalDate.class, ChronoLocalDate::from); queries.put(ChronoLocalDateTime.class, ChronoLocalDateTime::from); queries.put(ChronoZonedDateTime.class, ChronoZonedDateTime::from); queries.put(LocalDate.class, LocalDate::from); queries.put(LocalDateTime.class, LocalDateTime::from); queries.put(LocalTime.class, LocalTime::from); queries.put(OffsetDateTime.class, OffsetDateTime::from); queries.put(OffsetTime.class, OffsetTime::from); queries.put(Year.class, Year::from); queries.put(YearMonth.class, YearMonth::from); queries.put(ZonedDateTime.class, ZonedDateTime::from); TEMPORAL_QUERIES = Collections.unmodifiableMap(queries); } @Override protected Object convert(Object input, Class targetClass, JavaTimeConversionPattern annotation) { if (input == null) { throw new ArgumentConversionException("Cannot convert null to " + targetClass.getName()); } TemporalQuery temporalQuery = TEMPORAL_QUERIES.get(targetClass); if (temporalQuery == null) { throw new ArgumentConversionException("Cannot convert to " + targetClass.getName() + ": " + input); } String pattern = annotation.value(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return formatter.parse(input.toString(), temporalQuery); } } JavaTimeConversionPattern.java000066400000000000000000000026611455764576500365460ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.params.ParameterizedTest; /** * {@code @JavaTimeConversionPattern} is an annotation that allows a date/time * conversion pattern to be specified on a parameter of a * {@link ParameterizedTest @ParameterizedTest} method. * * @since 5.0 * @see org.junit.jupiter.params.ParameterizedTest * @see java.time.format.DateTimeFormatterBuilder#appendPattern(String) */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ConvertWith(JavaTimeArgumentConverter.class) @SuppressWarnings("exports") public @interface JavaTimeConversionPattern { /** * The date/time conversion pattern. * * @see java.time.format.DateTimeFormatterBuilder#appendPattern(String) */ String value(); } SimpleArgumentConverter.java000066400000000000000000000033161455764576500362640ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; /** * {@code SimpleArgumentConverter} is an abstract base class for * {@link ArgumentConverter} implementations that only need to know the target * type and do not need access to the {@link ParameterContext} to perform the * conversion. * * @since 5.0 * @see ArgumentConverter * @see TypedArgumentConverter */ @API(status = STABLE, since = "5.7") public abstract class SimpleArgumentConverter implements ArgumentConverter { public SimpleArgumentConverter() { } @Override public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return convert(source, context.getParameter().getType()); } /** * Convert the supplied {@code source} object into the supplied * {@code targetType}. * * @param source the source object to convert; may be {@code null} * @param targetType the target type the source object should be converted * into; never {@code null} * @return the converted object; may be {@code null} but only if the target * type is a reference type * @throws ArgumentConversionException in case an error occurs during the * conversion */ protected abstract Object convert(Object source, Class targetType) throws ArgumentConversionException; } StringToBooleanConverter.java000066400000000000000000000015551455764576500364040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import org.junit.platform.commons.util.Preconditions; class StringToBooleanConverter implements StringToObjectConverter { @Override public boolean canConvert(Class targetType) { return targetType == Boolean.class; } @Override public Object convert(String source, Class targetType) { boolean isTrue = "true".equalsIgnoreCase(source); Preconditions.condition(isTrue || "false".equalsIgnoreCase(source), () -> "String must be 'true' or 'false' (ignoring case): " + source); return isTrue; } } StringToCharacterConverter.java000066400000000000000000000014321455764576500367130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import org.junit.platform.commons.util.Preconditions; class StringToCharacterConverter implements StringToObjectConverter { @Override public boolean canConvert(Class targetType) { return targetType == Character.class; } @Override public Object convert(String source, Class targetType) { Preconditions.condition(source.length() == 1, () -> "String must have length of 1: " + source); return source.charAt(0); } } StringToClassConverter.java000066400000000000000000000021771455764576500360730ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import org.junit.platform.commons.util.ReflectionUtils; class StringToClassConverter implements StringToObjectConverter { @Override public boolean canConvert(Class targetType) { return targetType == Class.class; } @Override public Object convert(String source, Class targetType) throws Exception { throw new UnsupportedOperationException("Invoke convert(String, Class, ClassLoader) instead"); } @Override public Object convert(String className, Class targetType, ClassLoader classLoader) throws Exception { // @formatter:off return ReflectionUtils.tryToLoadClass(className, classLoader) .getOrThrow(cause -> new ArgumentConversionException( "Failed to convert String \"" + className + "\" to type java.lang.Class", cause)); // @formatter:on } } StringToCommonJavaTypesConverter.java000066400000000000000000000037041455764576500401020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static java.util.Collections.unmodifiableMap; import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Currency; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.function.Function; class StringToCommonJavaTypesConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; static { Map, Function> converters = new HashMap<>(); // java.io and java.nio converters.put(File.class, File::new); converters.put(Charset.class, Charset::forName); converters.put(Path.class, Paths::get); // java.net converters.put(URI.class, URI::create); converters.put(URL.class, StringToCommonJavaTypesConverter::toURL); // java.util converters.put(Currency.class, Currency::getInstance); converters.put(Locale.class, Locale::new); converters.put(UUID.class, UUID::fromString); CONVERTERS = unmodifiableMap(converters); } @Override public boolean canConvert(Class targetType) { return CONVERTERS.containsKey(targetType); } @Override public Object convert(String source, Class targetType) throws Exception { return CONVERTERS.get(targetType).apply(source); } private static URL toURL(String url) { try { return URI.create(url).toURL(); } catch (MalformedURLException ex) { throw new ArgumentConversionException("Failed to convert String \"" + url + "\" to type java.net.URL", ex); } } } StringToEnumConverter.java000066400000000000000000000013001455764576500357150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; class StringToEnumConverter implements StringToObjectConverter { @Override public boolean canConvert(Class targetType) { return targetType.isEnum(); } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Object convert(String source, Class targetType) throws Exception { return Enum.valueOf(targetType, source); } } StringToJavaTimeConverter.java000066400000000000000000000041431455764576500365210ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static java.util.Collections.unmodifiableMap; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.Period; import java.time.Year; import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.HashMap; import java.util.Map; import java.util.function.Function; class StringToJavaTimeConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; static { Map, Function> converters = new HashMap<>(); converters.put(Duration.class, Duration::parse); converters.put(Instant.class, Instant::parse); converters.put(LocalDate.class, LocalDate::parse); converters.put(LocalDateTime.class, LocalDateTime::parse); converters.put(LocalTime.class, LocalTime::parse); converters.put(MonthDay.class, MonthDay::parse); converters.put(OffsetDateTime.class, OffsetDateTime::parse); converters.put(OffsetTime.class, OffsetTime::parse); converters.put(Period.class, Period::parse); converters.put(Year.class, Year::parse); converters.put(YearMonth.class, YearMonth::parse); converters.put(ZonedDateTime.class, ZonedDateTime::parse); converters.put(ZoneId.class, ZoneId::of); converters.put(ZoneOffset.class, ZoneOffset::of); CONVERTERS = unmodifiableMap(converters); } @Override public boolean canConvert(Class targetType) { return CONVERTERS.containsKey(targetType); } @Override public Object convert(String source, Class targetType) throws Exception { return CONVERTERS.get(targetType).apply(source); } } StringToNumberConverter.java000066400000000000000000000031441455764576500362510ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static java.util.Collections.unmodifiableMap; import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; import java.util.function.Function; class StringToNumberConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; static { Map, Function> converters = new HashMap<>(); converters.put(Byte.class, Byte::decode); converters.put(Short.class, Short::decode); converters.put(Integer.class, Integer::decode); converters.put(Long.class, Long::decode); converters.put(Float.class, Float::valueOf); converters.put(Double.class, Double::valueOf); // Technically, BigInteger and BigDecimal constructors are covered by // FallbackStringToObjectConverter, but we have explicit conversion // configured for them anyway. converters.put(BigInteger.class, BigInteger::new); converters.put(BigDecimal.class, BigDecimal::new); CONVERTERS = unmodifiableMap(converters); } @Override public boolean canConvert(Class targetType) { return CONVERTERS.containsKey(targetType); } @Override public Object convert(String source, Class targetType) { return CONVERTERS.get(targetType).apply(source.replace("_", "")); } } StringToObjectConverter.java000066400000000000000000000031241455764576500362250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; /** * Internal API for converting arguments of type {@link String} to a specified * target type. */ interface StringToObjectConverter { /** * Determine if this converter can convert from a {@link String} to the * supplied target type (which is guaranteed to be a wrapper type for * primitives — for example, {@link Integer} instead of {@code int}). */ boolean canConvert(Class targetType); /** * Convert the supplied {@link String} to the supplied target type (which is * guaranteed to be a wrapper type for primitives — for example, * {@link Integer} instead of {@code int}). */ Object convert(String source, Class targetType) throws Exception; /** * Convert the supplied {@link String} to the supplied target type (which is * guaranteed to be a wrapper type for primitives — for example, * {@link Integer} instead of {@code int}). * *

The default implementation simply delegates to {@link #convert(String, Class)}. * Can be overridden by concrete implementations of this interface that need * access to the supplied {@link ClassLoader}. */ default Object convert(String source, Class targetType, ClassLoader classLoader) throws Exception { return convert(source, targetType); } } TypedArgumentConverter.java000066400000000000000000000057611455764576500361260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code TypedArgumentConverter} is an abstract base class for * {@link ArgumentConverter} implementations that always convert objects of a * given source type into a given target type. * * @param the type of the source argument to convert * @param the type of the target object to create from the source * @since 5.7 * @see ArgumentConverter * @see SimpleArgumentConverter */ @API(status = STABLE, since = "5.10") public abstract class TypedArgumentConverter implements ArgumentConverter { private final Class sourceType; private final Class targetType; /** * Create a new {@code TypedArgumentConverter}. * * @param sourceType the type of the argument to convert; never {@code null} * @param targetType the type of the target object to create from the source; * never {@code null} */ protected TypedArgumentConverter(Class sourceType, Class targetType) { this.sourceType = Preconditions.notNull(sourceType, "sourceType must not be null"); this.targetType = Preconditions.notNull(targetType, "targetType must not be null"); } @Override public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { if (source == null) { return convert(null); } if (!this.sourceType.isInstance(source)) { String message = String.format( "%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.", getClass().getSimpleName(), source.getClass().getName(), this.sourceType.getName()); throw new ArgumentConversionException(message); } if (!ReflectionUtils.isAssignableTo(this.targetType, context.getParameter().getType())) { String message = String.format("%s cannot convert to type [%s]. Only target type [%s] is supported.", getClass().getSimpleName(), context.getParameter().getType().getName(), this.targetType.getName()); throw new ArgumentConversionException(message); } return convert(this.sourceType.cast(source)); } /** * Convert the supplied {@code source} object of type {@code S} into an object * of type {@code T}. * * @param source the source object to convert; may be {@code null} * @return the converted object; may be {@code null} but only if the target * type is a reference type * @throws ArgumentConversionException if an error occurs during the * conversion */ protected abstract T convert(S source) throws ArgumentConversionException; } package-info.java000066400000000000000000000004031455764576500337560ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/** * {@link org.junit.jupiter.params.converter.ArgumentConverter ArgumentConverter} * implementations and the corresponding * {@link org.junit.jupiter.params.converter.ConvertWith @ConvertWith} annotation. */ package org.junit.jupiter.params.converter; junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/package-info.java000066400000000000000000000001371455764576500320320ustar00rootroot00000000000000/** * JUnit Jupiter extension for parameterized tests. */ package org.junit.jupiter.params; junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/000077500000000000000000000000001455764576500304745ustar00rootroot00000000000000AnnotationBasedArgumentsProvider.java000066400000000000000000000043051455764576500377340ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Annotation; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.util.Preconditions; /** * {@code AnnotationBasedArgumentsProvider} is an abstract base class for * {@link ArgumentsProvider} implementations that also need to consume an * annotation in order to provide the arguments. * * @since 5.10 * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.provider.Arguments * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.support.AnnotationConsumer */ @API(status = EXPERIMENTAL, since = "5.10") public abstract class AnnotationBasedArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { public AnnotationBasedArgumentsProvider() { } private A annotation; @Override public final void accept(A annotation) { Preconditions.notNull(annotation, "annotation must not be null"); this.annotation = annotation; } @Override public final Stream provideArguments(ExtensionContext context) { return provideArguments(context, this.annotation); } /** * Provide a {@link Stream} of {@link Arguments} — based on metadata in the * provided annotation — to be passed to a {@code @ParameterizedTest} method. * * @param context the current extension context; never {@code null} * @param annotation the annotation to process; never {@code null} * @return a stream of arguments; never {@code null} */ protected abstract Stream provideArguments(ExtensionContext context, A annotation); } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/Arguments.java000066400000000000000000000066261455764576500333160ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; /** * {@code Arguments} is an abstraction that provides access to an array of * objects to be used for invoking a {@code @ParameterizedTest} method. * *

A {@link java.util.stream.Stream} of such {@code Arguments} will * typically be provided by an {@link ArgumentsProvider}. * * @apiNote

This interface is specifically designed as a simple holder of * arguments of a parameterized test. Therefore, if you end up * {@linkplain java.util.stream.Stream#map(java.util.function.Function) transforming} * or * {@linkplain java.util.stream.Stream#filter(java.util.function.Predicate) filtering} * the arguments, you should consider using one of the following in intermediate * steps: * *

* *

Alternatively, you can use an * {@link org.junit.jupiter.params.converter.ArgumentConverter ArgumentConverter} * to convert some of the arguments from one type to another. * * @since 5.0 * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.converter.ArgumentConverter */ @API(status = STABLE, since = "5.7") public interface Arguments { /** * Get the arguments used for an invocation of the * {@code @ParameterizedTest} method. * * @apiNote If you need a type-safe way to access some or all of the arguments, * please read the {@linkplain Arguments class-level API note}. * * @return the arguments; must not be {@code null} */ Object[] get(); /** * Factory method for creating an instance of {@code Arguments} based on * the supplied {@code arguments}. * * @param arguments the arguments to be used for an invocation of the test * method; must not be {@code null} * @return an instance of {@code Arguments}; never {@code null} * @see #arguments(Object...) */ static Arguments of(Object... arguments) { Preconditions.notNull(arguments, "argument array must not be null"); return () -> arguments; } /** * Factory method for creating an instance of {@code Arguments} based on * the supplied {@code arguments}. * *

This method is an alias for {@link Arguments#of} and is * intended to be used when statically imported — for example, via: * {@code import static org.junit.jupiter.params.provider.Arguments.arguments;} * * @param arguments the arguments to be used for an invocation of the test * method; must not be {@code null} * @return an instance of {@code Arguments}; never {@code null} * @since 5.3 */ static Arguments arguments(Object... arguments) { return of(arguments); } } ArgumentsProvider.java000066400000000000000000000030141455764576500347360ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext; /** * An {@code ArgumentsProvider} is responsible for {@linkplain #provideArguments * providing} a stream of arguments to be passed to a {@code @ParameterizedTest} * method. * *

An {@code ArgumentsProvider} can be registered via the * {@link ArgumentsSource @ArgumentsSource} annotation. * *

Implementations must provide a no-args constructor. * * @since 5.0 * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.provider.Arguments * @see org.junit.jupiter.params.support.AnnotationConsumer */ @API(status = STABLE, since = "5.7") public interface ArgumentsProvider { /** * Provide a {@link Stream} of {@link Arguments} to be passed to a * {@code @ParameterizedTest} method. * * @param context the current extension context; never {@code null} * @return a stream of arguments; never {@code null} */ Stream provideArguments(ExtensionContext context) throws Exception; } ArgumentsSource.java000066400000000000000000000027171455764576500344150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ArgumentsSource} is a {@linkplain Repeatable repeatable} annotation * that is used to register {@linkplain ArgumentsProvider argument providers} * for the annotated test method. * *

{@code @ArgumentsSource} may also be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @ArgumentsSource}. * * @since 5.0 * @see org.junit.jupiter.params.provider.ArgumentsProvider */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(ArgumentsSources.class) @API(status = STABLE, since = "5.7") public @interface ArgumentsSource { /** * The type of {@link ArgumentsProvider} to be used. */ Class value(); } ArgumentsSources.java000066400000000000000000000024551455764576500345770ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ArgumentsSources} is a simple container for one or more * {@link ArgumentsSource} annotations. * *

Note, however, that use of the {@code @ArgumentsSources} container is completely * optional since {@code @ArgumentsSource} is a {@linkplain java.lang.annotation.Repeatable * repeatable} annotation. * * @since 5.0 * @see org.junit.jupiter.params.provider.ArgumentsSource */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") public @interface ArgumentsSources { /** * An array of one or more {@link ArgumentsSource @ArgumentsSource} * annotations. */ ArgumentsSource[] value(); } CsvArgumentsProvider.java000066400000000000000000000130161455764576500354150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.junit.jupiter.params.provider.CsvParserFactory.createParserFor; import static org.junit.platform.commons.util.CollectionUtils.toSet; import java.io.StringReader; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import com.univocity.parsers.csv.CsvParser; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * @since 5.0 */ class CsvArgumentsProvider extends AnnotationBasedArgumentsProvider { private static final String LINE_SEPARATOR = "\n"; private Set nullValues; private CsvParser csvParser; @Override protected Stream provideArguments(ExtensionContext context, CsvSource csvSource) { this.nullValues = toSet(csvSource.nullValues()); this.csvParser = createParserFor(csvSource); final boolean textBlockDeclared = !csvSource.textBlock().isEmpty(); Preconditions.condition(csvSource.value().length > 0 ^ textBlockDeclared, () -> "@CsvSource must be declared with either `value` or `textBlock` but not both"); return textBlockDeclared ? parseTextBlock(csvSource) : parseValueArray(csvSource); } private Stream parseTextBlock(CsvSource csvSource) { String textBlock = csvSource.textBlock(); boolean useHeadersInDisplayName = csvSource.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); try { List csvRecords = this.csvParser.parseAll(new StringReader(textBlock)); String[] headers = useHeadersInDisplayName ? getHeaders(this.csvParser) : null; AtomicInteger index = new AtomicInteger(0); for (String[] csvRecord : csvRecords) { index.incrementAndGet(); Preconditions.notNull(csvRecord, () -> "Record at index " + index + " contains invalid CSV: \"\"\"\n" + textBlock + "\n\"\"\""); argumentsList.add(processCsvRecord(csvRecord, this.nullValues, useHeadersInDisplayName, headers)); } } catch (Throwable throwable) { throw handleCsvException(throwable, csvSource); } return argumentsList.stream(); } private Stream parseValueArray(CsvSource csvSource) { boolean useHeadersInDisplayName = csvSource.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); try { String[] headers = null; AtomicInteger index = new AtomicInteger(0); for (String input : csvSource.value()) { index.incrementAndGet(); String[] csvRecord = this.csvParser.parseLine(input + LINE_SEPARATOR); // Lazily retrieve headers if necessary. if (useHeadersInDisplayName && headers == null) { headers = getHeaders(this.csvParser); continue; } Preconditions.notNull(csvRecord, () -> "Record at index " + index + " contains invalid CSV: \"" + input + "\""); argumentsList.add(processCsvRecord(csvRecord, this.nullValues, useHeadersInDisplayName, headers)); } } catch (Throwable throwable) { throw handleCsvException(throwable, csvSource); } return argumentsList.stream(); } // Cannot get parsed headers until after parsing has started. static String[] getHeaders(CsvParser csvParser) { return Arrays.stream(csvParser.getContext().parsedHeaders())// .map(String::trim)// .toArray(String[]::new); } /** * Processes custom null values, supports wrapping of column values in * {@link Named} if necessary (for CSV header support), and returns the * CSV record wrapped in an {@link Arguments} instance. */ static Arguments processCsvRecord(Object[] csvRecord, Set nullValues, boolean useHeadersInDisplayName, String[] headers) { // Nothing to process? if (nullValues.isEmpty() && !useHeadersInDisplayName) { return Arguments.of(csvRecord); } Preconditions.condition(!useHeadersInDisplayName || (csvRecord.length <= headers.length), () -> String.format( "The number of columns (%d) exceeds the number of supplied headers (%d) in CSV record: %s", csvRecord.length, headers.length, Arrays.toString(csvRecord))); Object[] arguments = new Object[csvRecord.length]; for (int i = 0; i < csvRecord.length; i++) { Object column = csvRecord[i]; if (nullValues.contains(column)) { column = null; } if (useHeadersInDisplayName) { column = Named.of(headers[i] + " = " + column, column); } arguments[i] = column; } return Arguments.of(arguments); } /** * @return this method always throws an exception and therefore never * returns anything; the return type is merely present to allow this * method to be supplied as the operand in a {@code throw} statement */ static RuntimeException handleCsvException(Throwable throwable, Annotation annotation) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); if (throwable instanceof PreconditionViolationException) { throw (PreconditionViolationException) throwable; } throw new CsvParsingException("Failed to parse CSV input configured via " + annotation, throwable); } } CsvFileArgumentsProvider.java000066400000000000000000000146231455764576500362220ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.getHeaders; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.handleCsvException; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.processCsvRecord; import static org.junit.jupiter.params.provider.CsvParserFactory.createParserFor; import static org.junit.platform.commons.util.CollectionUtils.toSet; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Spliterator; import java.util.stream.Stream; import com.univocity.parsers.csv.CsvParser; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; /** * @since 5.0 */ class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider { private final InputStreamProvider inputStreamProvider; private Charset charset; private int numLinesToSkip; private CsvParser csvParser; CsvFileArgumentsProvider() { this(DefaultInputStreamProvider.INSTANCE); } CsvFileArgumentsProvider(InputStreamProvider inputStreamProvider) { this.inputStreamProvider = inputStreamProvider; } @Override protected Stream provideArguments(ExtensionContext context, CsvFileSource csvFileSource) { this.charset = getCharsetFrom(csvFileSource); this.numLinesToSkip = csvFileSource.numLinesToSkip(); this.csvParser = createParserFor(csvFileSource); Stream resources = Arrays.stream(csvFileSource.resources()).map(inputStreamProvider::classpathResource); Stream files = Arrays.stream(csvFileSource.files()).map(inputStreamProvider::file); List sources = Stream.concat(resources, files).collect(toList()); // @formatter:off return Preconditions.notEmpty(sources, "Resources or files must not be empty") .stream() .map(source -> source.open(context)) .map(inputStream -> beginParsing(inputStream, csvFileSource)) .flatMap(parser -> toStream(parser, csvFileSource)); // @formatter:on } private Charset getCharsetFrom(CsvFileSource csvFileSource) { try { return Charset.forName(csvFileSource.encoding()); } catch (Exception ex) { throw new PreconditionViolationException("The charset supplied in " + csvFileSource + " is invalid", ex); } } private CsvParser beginParsing(InputStream inputStream, CsvFileSource csvFileSource) { try { this.csvParser.beginParsing(inputStream, this.charset); } catch (Throwable throwable) { handleCsvException(throwable, csvFileSource); } return this.csvParser; } private Stream toStream(CsvParser csvParser, CsvFileSource csvFileSource) { CsvParserIterator iterator = new CsvParserIterator(csvParser, csvFileSource); return stream(spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) // .skip(this.numLinesToSkip) // .onClose(() -> { try { csvParser.stopParsing(); } catch (Throwable throwable) { handleCsvException(throwable, csvFileSource); } }); } private static class CsvParserIterator implements Iterator { private final CsvParser csvParser; private final CsvFileSource csvFileSource; private final boolean useHeadersInDisplayName; private final Set nullValues; private Arguments nextArguments; private String[] headers; CsvParserIterator(CsvParser csvParser, CsvFileSource csvFileSource) { this.csvParser = csvParser; this.csvFileSource = csvFileSource; this.useHeadersInDisplayName = csvFileSource.useHeadersInDisplayName(); this.nullValues = toSet(csvFileSource.nullValues()); advance(); } @Override public boolean hasNext() { return this.nextArguments != null; } @Override public Arguments next() { Arguments result = this.nextArguments; advance(); return result; } private void advance() { try { String[] csvRecord = this.csvParser.parseNext(); if (csvRecord != null) { // Lazily retrieve headers if necessary. if (this.useHeadersInDisplayName && this.headers == null) { this.headers = getHeaders(this.csvParser); } this.nextArguments = processCsvRecord(csvRecord, this.nullValues, this.useHeadersInDisplayName, this.headers); } else { this.nextArguments = null; } } catch (Throwable throwable) { handleCsvException(throwable, this.csvFileSource); } } } @FunctionalInterface private interface Source { InputStream open(ExtensionContext context); } interface InputStreamProvider { InputStream openClasspathResource(Class baseClass, String path); InputStream openFile(String path); default Source classpathResource(String path) { return context -> openClasspathResource(context.getRequiredTestClass(), path); } default Source file(String path) { return context -> openFile(path); } } private static class DefaultInputStreamProvider implements InputStreamProvider { private static final DefaultInputStreamProvider INSTANCE = new DefaultInputStreamProvider(); @Override public InputStream openClasspathResource(Class baseClass, String path) { Preconditions.notBlank(path, () -> "Classpath resource [" + path + "] must not be null or blank"); InputStream inputStream = baseClass.getResourceAsStream(path); return Preconditions.notNull(inputStream, () -> "Classpath resource [" + path + "] does not exist"); } @Override public InputStream openFile(String path) { Preconditions.notBlank(path, () -> "File [" + path + "] must not be null or blank"); try { return Files.newInputStream(Paths.get(path)); } catch (IOException e) { throw new JUnitException("File [" + path + "] could not be read", e); } } } } CsvFileSource.java000066400000000000000000000162271455764576500340040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @CsvFileSource} is an {@link ArgumentsSource} which is used to load * comma-separated value (CSV) files from one or more classpath {@link #resources} * or {@link #files}. * *

The CSV records parsed from these resources and files will be provided as * arguments to the annotated {@code @ParameterizedTest} method. Note that the * first record may optionally be used to supply CSV headers (see * {@link #useHeadersInDisplayName}). * *

Any line beginning with a {@code #} symbol will be interpreted as a comment * and will be ignored. * *

The column delimiter (which defaults to a comma ({@code ,})) can be customized * via either {@link #delimiter} or {@link #delimiterString}. * *

In contrast to the default syntax used in {@code @CsvSource}, {@code @CsvFileSource} * uses a double quote ({@code "}) as its quote character by default, but this can * be changed via {@link #quoteCharacter}. An empty, quoted value ({@code ""}) * results in an empty {@link String} unless the {@link #emptyValue} attribute is * set; whereas, an entirely empty value is interpreted as a {@code null} * reference. By specifying one or more {@link #nullValues} a custom value can be * interpreted as a {@code null} reference (see the User Guide for an example). An * {@link org.junit.jupiter.params.converter.ArgumentConversionException * ArgumentConversionException} is thrown if the target type of a {@code null} * reference is a primitive type. * *

NOTE: An unquoted empty value will always be converted to a * {@code null} reference regardless of any custom values configured via the * {@link #nullValues} attribute. * *

Except within a quoted string, leading and trailing whitespace in a CSV * column is trimmed by default. This behavior can be changed by setting the * {@link #ignoreLeadingAndTrailingWhitespace} attribute to {@code true}. * * @since 5.0 * @see CsvSource * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(CsvFileArgumentsProvider.class) @SuppressWarnings("exports") public @interface CsvFileSource { /** * The CSV classpath resources to use as the sources of arguments; must not * be empty unless {@link #files} is non-empty. */ String[] resources() default {}; /** * The CSV files to use as the sources of arguments; must not be empty * unless {@link #resources} is non-empty. */ String[] files() default {}; /** * The encoding to use when reading the CSV files; must be a valid charset. * *

Defaults to {@code "UTF-8"}. * * @see java.nio.charset.StandardCharsets */ String encoding() default "UTF-8"; /** * The line separator to use when reading the CSV files; must consist of 1 * or 2 characters, typically {@code "\r"}, {@code "\n"}, or {@code "\r\n"}. * *

Defaults to {@code "\n"}. */ String lineSeparator() default "\n"; /** * Configures whether the first CSV record should be treated as header names * for columns. * *

When set to {@code true}, the header names will be used in the * generated display name for each {@code @ParameterizedTest} method * invocation. When using this feature, you must ensure that the display name * pattern for {@code @ParameterizedTest} includes * {@value org.junit.jupiter.params.ParameterizedTest#ARGUMENTS_PLACEHOLDER} instead of * {@value org.junit.jupiter.params.ParameterizedTest#ARGUMENTS_WITH_NAMES_PLACEHOLDER} * as demonstrated in the example below. * *

Defaults to {@code false}. * * *

Example

*
	 * {@literal @}ParameterizedTest(name = "[{index}] {arguments}")
	 * {@literal @}CsvFileSource(resources = "fruits.csv", useHeadersInDisplayName = true)
	 * void test(String fruit, int rank) {
	 *     // ...
	 * }
* * @since 5.8.2 */ @API(status = STABLE, since = "5.10") boolean useHeadersInDisplayName() default false; /** * The quote character to use for quoted strings. * *

Defaults to a double quote ({@code "}). * *

You may change the quote character to anything that makes sense for * your use case. * * @since 5.8.2 */ @API(status = STABLE, since = "5.10") char quoteCharacter() default '"'; /** * The column delimiter character to use when reading the CSV files. * *

This is an alternative to {@link #delimiterString} and cannot be * used in conjunction with {@link #delimiterString}. * *

Defaults implicitly to {@code ','}, if neither delimiter attribute is * explicitly set. */ char delimiter() default '\0'; /** * The column delimiter string to use when reading the CSV files. * *

This is an alternative to {@link #delimiter} and cannot be used in * conjunction with {@link #delimiter}. * *

Defaults implicitly to {@code ","}, if neither delimiter attribute is * explicitly set. * * @since 5.6 */ String delimiterString() default ""; /** * The number of lines to skip when reading the CSV files. * *

Typically used to skip header lines. * *

Defaults to {@code 0}. * * @since 5.1 */ int numLinesToSkip() default 0; /** * The empty value to use when reading the CSV files. * *

This value replaces quoted empty strings read from the input. * *

Defaults to {@code ""}. * * @since 5.5 */ String emptyValue() default ""; /** * A list of strings that should be interpreted as {@code null} references. * *

For example, you may wish for certain values such as {@code "N/A"} or * {@code "NIL"} to be converted to {@code null} references. * *

Please note that unquoted empty values will always be converted * to {@code null} references regardless of the value of this {@code nullValues} * attribute; whereas, a quoted empty string will be treated as an * {@link #emptyValue}. * *

Defaults to {@code {}}. * * @since 5.6 */ String[] nullValues() default {}; /** * The maximum number of characters allowed per CSV column. * *

Must be a positive number. * *

Defaults to {@code 4096}. * * @since 5.7 */ @API(status = STABLE, since = "5.10") int maxCharsPerColumn() default 4096; /** * Controls whether leading and trailing whitespace characters of unquoted * CSV columns should be ignored. * *

Defaults to {@code true}. * * @since 5.8 */ @API(status = STABLE, since = "5.10") boolean ignoreLeadingAndTrailingWhitespace() default true; } CsvParserFactory.java000066400000000000000000000077121455764576500345270ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import java.lang.annotation.Annotation; import com.univocity.parsers.csv.CsvParser; import com.univocity.parsers.csv.CsvParserSettings; import org.junit.platform.commons.util.Preconditions; /** * @since 5.6 */ class CsvParserFactory { private static final String DEFAULT_DELIMITER = ","; private static final String LINE_SEPARATOR = "\n"; private static final char EMPTY_CHAR = '\0'; private static final boolean COMMENT_PROCESSING_FOR_CSV_FILE_SOURCE = true; static CsvParser createParserFor(CsvSource annotation) { String delimiter = selectDelimiter(annotation, annotation.delimiter(), annotation.delimiterString()); boolean commentProcessingEnabled = !annotation.textBlock().isEmpty(); return createParser(delimiter, LINE_SEPARATOR, annotation.quoteCharacter(), annotation.emptyValue(), annotation.maxCharsPerColumn(), commentProcessingEnabled, annotation.useHeadersInDisplayName(), annotation.ignoreLeadingAndTrailingWhitespace()); } static CsvParser createParserFor(CsvFileSource annotation) { String delimiter = selectDelimiter(annotation, annotation.delimiter(), annotation.delimiterString()); return createParser(delimiter, annotation.lineSeparator(), annotation.quoteCharacter(), annotation.emptyValue(), annotation.maxCharsPerColumn(), COMMENT_PROCESSING_FOR_CSV_FILE_SOURCE, annotation.useHeadersInDisplayName(), annotation.ignoreLeadingAndTrailingWhitespace()); } private static String selectDelimiter(Annotation annotation, char delimiter, String delimiterString) { Preconditions.condition(delimiter == EMPTY_CHAR || delimiterString.isEmpty(), () -> "The delimiter and delimiterString attributes cannot be set simultaneously in " + annotation); if (delimiter != EMPTY_CHAR) { return String.valueOf(delimiter); } if (!delimiterString.isEmpty()) { return delimiterString; } return DEFAULT_DELIMITER; } private static CsvParser createParser(String delimiter, String lineSeparator, char quote, String emptyValue, int maxCharsPerColumn, boolean commentProcessingEnabled, boolean headerExtractionEnabled, boolean ignoreLeadingAndTrailingWhitespace) { return new CsvParser(createParserSettings(delimiter, lineSeparator, quote, emptyValue, maxCharsPerColumn, commentProcessingEnabled, headerExtractionEnabled, ignoreLeadingAndTrailingWhitespace)); } private static CsvParserSettings createParserSettings(String delimiter, String lineSeparator, char quote, String emptyValue, int maxCharsPerColumn, boolean commentProcessingEnabled, boolean headerExtractionEnabled, boolean ignoreLeadingAndTrailingWhitespace) { CsvParserSettings settings = new CsvParserSettings(); settings.setHeaderExtractionEnabled(headerExtractionEnabled); settings.getFormat().setDelimiter(delimiter); settings.getFormat().setLineSeparator(lineSeparator); settings.getFormat().setQuote(quote); settings.getFormat().setQuoteEscape(quote); settings.setEmptyValue(emptyValue); settings.setCommentProcessingEnabled(commentProcessingEnabled); settings.setAutoConfigurationEnabled(false); settings.setIgnoreLeadingWhitespaces(ignoreLeadingAndTrailingWhitespace); settings.setIgnoreTrailingWhitespaces(ignoreLeadingAndTrailingWhitespace); Preconditions.condition(maxCharsPerColumn > 0, () -> "maxCharsPerColumn must be a positive number: " + maxCharsPerColumn); settings.setMaxCharsPerColumn(maxCharsPerColumn); // Do not use the built-in support for skipping rows/lines since it will // throw an IllegalArgumentException if the file does not contain at least // the number of specified lines to skip. // settings.setNumberOfRowsToSkip(annotation.numLinesToSkip()); return settings; } } CsvParsingException.java000066400000000000000000000016441455764576500352230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Thrown if an error is encountered while parsing CSV input. * * @since 5.3 * @see CsvSource * @see CsvFileSource */ @API(status = STABLE, since = "5.7") public class CsvParsingException extends JUnitException { private static final long serialVersionUID = 1L; public CsvParsingException(String message) { super(message); } public CsvParsingException(String message, Throwable cause) { super(message, cause); } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSource.java000066400000000000000000000237421455764576500332630ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @CsvSource} is an {@link ArgumentsSource} which reads comma-separated * values (CSV) from one or more CSV records supplied via the {@link #value} * attribute or {@link #textBlock} attribute. * *

The supplied values will be provided as arguments to the annotated * {@code @ParameterizedTest} method. * *

The column delimiter (which defaults to a comma ({@code ,})) can be customized * via either {@link #delimiter} or {@link #delimiterString}. * *

By default, {@code @CsvSource} uses a single quote ({@code '}) as its quote * character, but this can be changed via {@link #quoteCharacter}. See the * {@code 'lemon, lime'} examples in the documentation for the {@link #value} * and {@link #textBlock} attributes. An empty, quoted value ({@code ''}) results * in an empty {@link String} unless the {@link #emptyValue} attribute is set; * whereas, an entirely empty value is interpreted as a {@code null} reference. * By specifying one or more {@link #nullValues} a custom value can be interpreted * as a {@code null} reference (see the User Guide for an example). An * {@link org.junit.jupiter.params.converter.ArgumentConversionException * ArgumentConversionException} is thrown if the target type of a {@code null} * reference is a primitive type. * *

NOTE: An unquoted empty value will always be converted to a * {@code null} reference regardless of any custom values configured via the * {@link #nullValues} attribute. * *

Except within a quoted string, leading and trailing whitespace in a CSV * column is trimmed by default. This behavior can be changed by setting the * {@link #ignoreLeadingAndTrailingWhitespace} attribute to {@code true}. * *

In general, CSV records should not contain explicit newlines ({@code \n}) * unless they are placed within quoted strings. Note that CSV records supplied * via {@link #textBlock} will implicitly contain newlines at the end of each * physical line within the text block. Thus, if a CSV column wraps across a * new line in a text block, the column must be a quoted string. * * @since 5.0 * @see CsvFileSource * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(CsvArgumentsProvider.class) @SuppressWarnings("exports") public @interface CsvSource { /** * The CSV records to use as the source of arguments; must not be empty. * *

Defaults to an empty array. You therefore must supply CSV content * via this attribute or the {@link #textBlock} attribute. * *

Each value corresponds to a record in a CSV file and will be split using * the specified {@link #delimiter} or {@link #delimiterString}. Note that * the first value may optionally be used to supply CSV headers (see * {@link #useHeadersInDisplayName}). * *

If text block syntax is supported by your programming language, * you may find it more convenient to declare your CSV content via the * {@link #textBlock} attribute. * *

Example

*
	 * {@literal @}ParameterizedTest
	 * {@literal @}CsvSource({
	 *     "apple,         1",
	 *     "banana,        2",
	 *     "'lemon, lime', 0xF1",
	 *     "strawberry,    700_000"
	 * })
	 * void test(String fruit, int rank) {
	 *     // ...
	 * }
* * @see #textBlock */ String[] value() default {}; /** * The CSV records to use as the source of arguments, supplied as a single * text block; must not be empty. * *

Defaults to an empty string. You therefore must supply CSV content * via this attribute or the {@link #value} attribute. * *

Text block syntax is supported by various languages on the JVM * including Java SE 15 or higher. If text blocks are not supported, you * should declare your CSV content via the {@link #value} attribute. * *

Each record in the text block corresponds to a record in a CSV file and will * be split using the specified {@link #delimiter} or {@link #delimiterString}. * Note that the first record may optionally be used to supply CSV headers (see * {@link #useHeadersInDisplayName}). * *

In contrast to CSV records supplied via {@link #value}, a text block * can contain comments. Any line beginning with a hash tag ({@code #}) will * be treated as a comment and ignored. Note, however, that the {@code #} * symbol must be the first character on the line without any leading * whitespace. It is therefore recommended that the closing text block * delimiter {@code """} be placed either at the end of the last line of * input or on the following line, vertically aligned with the rest of the * input (as can be seen in the example below). * *

Java's text block * feature automatically removes incidental whitespace when the code * is compiled. However other JVM languages such as Groovy and Kotlin do not. * Thus, if you are using a programming language other than Java and your text * block contains comments or new lines within quoted strings, you will need * to ensure that there is no leading whitespace within your text block. * *

Example

*
	 * {@literal @}ParameterizedTest
	 * {@literal @}CsvSource(quoteCharacter = '"', textBlock = """
	 *     # FRUIT,       RANK
	 *     apple,         1
	 *     banana,        2
	 *     "lemon, lime", 0xF1
	 *     strawberry,    700_000
	 *     """)
	 * void test(String fruit, int rank) {
	 *     // ...
	 * }
* * @since 5.8.1 * @see #value * @see #quoteCharacter */ @API(status = STABLE, since = "5.10") String textBlock() default ""; /** * Configures whether the first CSV record should be treated as header names * for columns. * *

When set to {@code true}, the header names will be used in the * generated display name for each {@code @ParameterizedTest} method * invocation. When using this feature, you must ensure that the display name * pattern for {@code @ParameterizedTest} includes * {@value org.junit.jupiter.params.ParameterizedTest#ARGUMENTS_PLACEHOLDER} instead of * {@value org.junit.jupiter.params.ParameterizedTest#ARGUMENTS_WITH_NAMES_PLACEHOLDER} * as demonstrated in the example below. * *

Defaults to {@code false}. * *

Example

*
	 * {@literal @}ParameterizedTest(name = "[{index}] {arguments}")
	 * {@literal @}CsvSource(useHeadersInDisplayName = true, textBlock = """
	 *     FRUIT,         RANK
	 *     apple,         1
	 *     banana,        2
	 *     'lemon, lime', 0xF1
	 *     strawberry,    700_000
	 *     """)
	 * void test(String fruit, int rank) {
	 *     // ...
	 * }
* * @since 5.8.2 */ @API(status = STABLE, since = "5.10") boolean useHeadersInDisplayName() default false; /** * The quote character to use for quoted strings. * *

Defaults to a single quote ({@code '}). * *

You may change the quote character to anything that makes sense for * your use case; however, the primary use case is to allow you to use double * quotes in {@link #textBlock}. * * @since 5.8.2 * @see #textBlock */ @API(status = STABLE, since = "5.10") char quoteCharacter() default '\''; /** * The column delimiter character to use when reading the {@linkplain #value records}. * *

This is an alternative to {@link #delimiterString} and cannot be * used in conjunction with {@link #delimiterString}. * *

Defaults implicitly to {@code ','}, if neither delimiter attribute is * explicitly set. */ char delimiter() default '\0'; /** * The column delimiter string to use when reading the {@linkplain #value records}. * *

This is an alternative to {@link #delimiter} and cannot be used in * conjunction with {@link #delimiter}. * *

Defaults implicitly to {@code ","}, if neither delimiter attribute is * explicitly set. * * @since 5.6 */ String delimiterString() default ""; /** * The empty value to use when reading the {@linkplain #value records}. * *

This value replaces quoted empty strings read from the input. * *

Defaults to {@code ""}. * * @since 5.5 */ String emptyValue() default ""; /** * A list of strings that should be interpreted as {@code null} references. * *

For example, you may wish for certain values such as {@code "N/A"} or * {@code "NIL"} to be converted to {@code null} references. * *

Please note that unquoted empty values will always be converted * to {@code null} references regardless of the value of this {@code nullValues} * attribute; whereas, a quoted empty string will be treated as an * {@link #emptyValue}. * *

Defaults to {@code {}}. * * @since 5.6 */ String[] nullValues() default {}; /** * The maximum number of characters allowed per CSV column. * *

Must be a positive number. * *

Defaults to {@code 4096}. * * @since 5.7 */ @API(status = STABLE, since = "5.10") int maxCharsPerColumn() default 4096; /** * Controls whether leading and trailing whitespace characters of unquoted * CSV columns should be ignored. * *

Defaults to {@code true}. * * @since 5.8 */ @API(status = STABLE, since = "5.10") boolean ignoreLeadingAndTrailingWhitespace() default true; } EmptyArgumentsProvider.java000066400000000000000000000067321455764576500357670ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.commons.util.ReflectionUtils.newInstance; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Optional; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; /** * @since 5.4 * @see EmptySource */ class EmptyArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { Method testMethod = context.getRequiredTestMethod(); Class[] parameterTypes = testMethod.getParameterTypes(); Preconditions.condition(parameterTypes.length > 0, () -> String.format( "@EmptySource cannot provide an empty argument to method [%s]: the method does not declare any formal parameters.", testMethod.toGenericString())); Class parameterType = parameterTypes[0]; if (String.class.equals(parameterType)) { return Stream.of(arguments("")); } if (Collection.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptySet())); } if (List.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyList())); } if (Set.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptySet())); } if (SortedSet.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptySortedSet())); } if (NavigableSet.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyNavigableSet())); } if (Map.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyMap())); } if (SortedMap.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptySortedMap())); } if (NavigableMap.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyNavigableMap())); } if (Collection.class.isAssignableFrom(parameterType) || Map.class.isAssignableFrom(parameterType)) { Optional> defaultConstructor = getDefaultConstructor(parameterType); if (defaultConstructor.isPresent()) { return Stream.of(arguments(newInstance(defaultConstructor.get()))); } } if (parameterType.isArray()) { Object array = Array.newInstance(parameterType.getComponentType(), 0); return Stream.of(arguments(array)); } // else throw new PreconditionViolationException( String.format("@EmptySource cannot provide an empty argument to method [%s]: [%s] is not a supported type.", testMethod.toGenericString(), parameterType.getName())); } private static Optional> getDefaultConstructor(Class clazz) { try { return Optional.of(clazz.getConstructor()); } catch (NoSuchMethodException e) { return Optional.empty(); } } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java000066400000000000000000000037771455764576500336340ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @EmptySource} is an {@link ArgumentsSource} which provides a single * empty argument to the annotated {@code @ParameterizedTest} method. * *

Supported Parameter Types

* *

This argument source will only provide an empty argument for the following * method parameter types. * *

    *
  • {@link java.lang.String}
  • *
  • {@link java.util.Collection} and concrete subtypes with a public no-arg constructor
  • *
  • {@link java.util.List}
  • *
  • {@link java.util.Set}
  • *
  • {@link java.util.SortedSet}
  • *
  • {@link java.util.NavigableSet}
  • *
  • {@link java.util.Map} and concrete subtypes with a public no-arg constructor
  • *
  • {@link java.util.SortedMap}
  • *
  • {@link java.util.NavigableMap}
  • *
  • primitive arrays — for example {@code int[]}, {@code char[][]}, etc.
  • *
  • object arrays — for example {@code String[]}, {@code Integer[][]}, etc.
  • *
* * @since 5.4 * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest * @see NullSource * @see NullAndEmptySource */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(EmptyArgumentsProvider.class) @SuppressWarnings("exports") public @interface EmptySource { } EnumArgumentsProvider.java000066400000000000000000000047701455764576500355750ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toSet; import java.lang.reflect.Method; import java.util.EnumSet; import java.util.Set; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.util.Preconditions; /** * @since 5.0 */ class EnumArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override protected Stream provideArguments(ExtensionContext context, EnumSource enumSource) { Set> constants = getEnumConstants(context, enumSource); EnumSource.Mode mode = enumSource.mode(); String[] declaredConstantNames = enumSource.names(); if (declaredConstantNames.length > 0) { Set uniqueNames = stream(declaredConstantNames).collect(toSet()); Preconditions.condition(uniqueNames.size() == declaredConstantNames.length, () -> "Duplicate enum constant name(s) found in " + enumSource); mode.validate(enumSource, constants, uniqueNames); constants.removeIf(constant -> !mode.select(constant, uniqueNames)); } return constants.stream().map(Arguments::of); } private > Set getEnumConstants(ExtensionContext context, EnumSource enumSource) { Class enumClass = determineEnumClass(context, enumSource); return EnumSet.allOf(enumClass); } @SuppressWarnings({ "unchecked", "rawtypes" }) private > Class determineEnumClass(ExtensionContext context, EnumSource enumSource) { Class enumClass = enumSource.value(); if (enumClass.equals(NullEnum.class)) { Method method = context.getRequiredTestMethod(); Class[] parameterTypes = method.getParameterTypes(); Preconditions.condition(parameterTypes.length > 0, () -> "Test method must declare at least one parameter: " + method.toGenericString()); Preconditions.condition(Enum.class.isAssignableFrom(parameterTypes[0]), () -> "First parameter must reference an Enum type (alternatively, use the annotation's 'value' attribute to specify the type explicitly): " + method.toGenericString()); enumClass = parameterTypes[0]; } return enumClass; } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java000066400000000000000000000136231455764576500334310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Set; import java.util.function.BiPredicate; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; /** * {@code @EnumSource} is an {@link ArgumentsSource} for constants of * an {@link Enum}. * *

The enum constants will be provided as arguments to the annotated * {@code @ParameterizedTest} method. * *

The enum type can be specified explicitly using the {@link #value} * attribute. Otherwise, the declared type of the first parameter of the * {@code @ParameterizedTest} method is used. * *

The set of enum constants can be restricted via the {@link #names} and * {@link #mode} attributes. * * @since 5.0 * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(EnumArgumentsProvider.class) @SuppressWarnings("exports") public @interface EnumSource { /** * The enum type that serves as the source of the enum constants. * *

If this attribute is not set explicitly, the declared type of the * first parameter of the {@code @ParameterizedTest} method is used. * * @see #names * @see #mode */ Class> value() default NullEnum.class; /** * The names of enum constants to provide, or regular expressions to select * the names of enum constants to provide. * *

If no names or regular expressions are specified, all enum constants * declared in the specified {@linkplain #value enum type} will be provided. * *

The {@link #mode} determines how the names are interpreted. * * @see #value * @see #mode */ String[] names() default {}; /** * The enum constant selection mode. * *

Defaults to {@link Mode#INCLUDE INCLUDE}. * * @see Mode#INCLUDE * @see Mode#EXCLUDE * @see Mode#MATCH_ALL * @see Mode#MATCH_ANY * @see Mode#MATCH_NONE * @see #names */ Mode mode() default Mode.INCLUDE; /** * Enumeration of modes for selecting enum constants by name. */ enum Mode { /** * Select only those enum constants whose names are supplied via the * {@link EnumSource#names} attribute. */ INCLUDE(Mode::validateNames, (name, names) -> names.contains(name)), /** * Select all declared enum constants except those supplied via the * {@link EnumSource#names} attribute. */ EXCLUDE(Mode::validateNames, (name, names) -> !names.contains(name)), /** * Select only those enum constants whose names match all patterns supplied * via the {@link EnumSource#names} attribute. * * @see java.util.stream.Stream#allMatch(java.util.function.Predicate) */ MATCH_ALL(Mode::validatePatterns, (name, patterns) -> patterns.stream().allMatch(name::matches)), /** * Select only those enum constants whose names match any pattern supplied * via the {@link EnumSource#names} attribute. * * @see java.util.stream.Stream#anyMatch(java.util.function.Predicate) */ MATCH_ANY(Mode::validatePatterns, (name, patterns) -> patterns.stream().anyMatch(name::matches)), /** * Select only those enum constants whose names match none of the patterns supplied * via the {@link EnumSource#names} attribute. * * @since 5.9 * @see java.util.stream.Stream#noneMatch(java.util.function.Predicate) */ @API(status = EXPERIMENTAL, since = "5.9") MATCH_NONE(Mode::validatePatterns, (name, patterns) -> patterns.stream().noneMatch(name::matches)); private final Validator validator; private final BiPredicate> selector; Mode(Validator validator, BiPredicate> selector) { this.validator = validator; this.selector = selector; } void validate(EnumSource enumSource, Set> constants, Set names) { Preconditions.notNull(enumSource, "EnumSource must not be null"); Preconditions.notNull(names, "names must not be null"); validator.validate(enumSource, constants, names); } boolean select(Enum constant, Set names) { Preconditions.notNull(constant, "Enum constant must not be null"); Preconditions.notNull(names, "names must not be null"); return selector.test(constant.name(), names); } private static void validateNames(EnumSource enumSource, Set> constants, Set names) { Set allNames = constants.stream().map(Enum::name).collect(toSet()); Preconditions.condition(allNames.containsAll(names), () -> "Invalid enum constant name(s) in " + enumSource + ". Valid names include: " + allNames); } private static void validatePatterns(EnumSource enumSource, Set> constants, Set names) { try { names.forEach(Pattern::compile); } catch (PatternSyntaxException e) { throw new PreconditionViolationException( "Pattern compilation failed for a regular expression supplied in " + enumSource, e); } } private interface Validator { void validate(EnumSource enumSource, Set> constants, Set names); } } } MethodArgumentsProvider.java000066400000000000000000000222311455764576500361010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.lang.String.format; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import static org.junit.platform.commons.util.CollectionUtils.isConvertibleToStream; import java.lang.reflect.Method; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; /** * @since 5.0 */ class MethodArgumentsProvider extends AnnotationBasedArgumentsProvider { private static final Predicate isFactoryMethod = // method -> isConvertibleToStream(method.getReturnType()) && !isTestMethod(method); @Override protected Stream provideArguments(ExtensionContext context, MethodSource methodSource) { Class testClass = context.getRequiredTestClass(); Method testMethod = context.getRequiredTestMethod(); Object testInstance = context.getTestInstance().orElse(null); String[] methodNames = methodSource.value(); // @formatter:off return stream(methodNames) .map(factoryMethodName -> findFactoryMethod(testClass, testMethod, factoryMethodName)) .map(factoryMethod -> validateFactoryMethod(factoryMethod, testInstance)) .map(factoryMethod -> context.getExecutableInvoker().invoke(factoryMethod, testInstance)) .flatMap(CollectionUtils::toStream) .map(MethodArgumentsProvider::toArguments); // @formatter:on } private static Method findFactoryMethod(Class testClass, Method testMethod, String factoryMethodName) { String originalFactoryMethodName = factoryMethodName; // If the user did not provide a factory method name, find a "default" local // factory method with the same name as the parameterized test method. if (StringUtils.isBlank(factoryMethodName)) { factoryMethodName = testMethod.getName(); return findFactoryMethodBySimpleName(testClass, testMethod, factoryMethodName); } // Convert local factory method name to fully-qualified method name. if (!looksLikeAFullyQualifiedMethodName(factoryMethodName)) { factoryMethodName = testClass.getName() + "#" + factoryMethodName; } // Find factory method using fully-qualified name. Method factoryMethod = findFactoryMethodByFullyQualifiedName(testClass, testMethod, factoryMethodName); // Ensure factory method has a valid return type and is not a test method. Preconditions.condition(isFactoryMethod.test(factoryMethod), () -> format( "Could not find valid factory method [%s] for test class [%s] but found the following invalid candidate: %s", originalFactoryMethodName, testClass.getName(), factoryMethod)); return factoryMethod; } private static boolean looksLikeAFullyQualifiedMethodName(String factoryMethodName) { if (factoryMethodName.contains("#")) { return true; } int indexOfFirstDot = factoryMethodName.indexOf('.'); if (indexOfFirstDot == -1) { return false; } int indexOfLastOpeningParenthesis = factoryMethodName.lastIndexOf('('); if (indexOfLastOpeningParenthesis > 0) { // Exclude simple/local method names with parameters return indexOfFirstDot < indexOfLastOpeningParenthesis; } // If we get this far, we conclude the supplied factory method name "looks" // like it was intended to be a fully-qualified method name, even if the // syntax is invalid. We do this in order to provide better diagnostics for // the user when a fully-qualified method name is in fact invalid. return true; } // package-private for testing static Method findFactoryMethodByFullyQualifiedName(Class testClass, Method testMethod, String fullyQualifiedMethodName) { String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); String className = methodParts[0]; String methodName = methodParts[1]; String methodParameters = methodParts[2]; ClassLoader classLoader = ClassLoaderUtils.getClassLoader(testClass); Class clazz = loadRequiredClass(className, classLoader); // Attempt to find an exact match first. Method factoryMethod = ReflectionUtils.findMethod(clazz, methodName, methodParameters).orElse(null); if (factoryMethod != null) { return factoryMethod; } boolean explicitParameterListSpecified = // StringUtils.isNotBlank(methodParameters) || fullyQualifiedMethodName.endsWith("()"); // If we didn't find an exact match but an explicit parameter list was specified, // that's a user configuration error. Preconditions.condition(!explicitParameterListSpecified, () -> format("Could not find factory method [%s(%s)] in class [%s]", methodName, methodParameters, className)); // Otherwise, fall back to the same lenient search semantics that are used // to locate a "default" local factory method. return findFactoryMethodBySimpleName(clazz, testMethod, methodName); } /** * Find the factory method by searching for all methods in the given {@code clazz} * with the desired {@code factoryMethodName} which have return types that can be * converted to a {@link Stream}, ignoring the {@code testMethod} itself as well * as any {@code @Test}, {@code @TestTemplate}, or {@code @TestFactory} methods * with the same name. * @return the single factory method matching the search criteria * @throws PreconditionViolationException if the factory method was not found or * multiple competing factory methods with the same name were found */ private static Method findFactoryMethodBySimpleName(Class clazz, Method testMethod, String factoryMethodName) { Predicate isCandidate = candidate -> factoryMethodName.equals(candidate.getName()) && !testMethod.equals(candidate); List candidates = ReflectionUtils.findMethods(clazz, isCandidate); List factoryMethods = candidates.stream().filter(isFactoryMethod).collect(toList()); Preconditions.condition(factoryMethods.size() > 0, () -> { // If we didn't find the factory method using the isFactoryMethod Predicate, perhaps // the specified factory method has an invalid return type or is a test method. // In that case, we report the invalid candidates that were found. if (candidates.size() > 0) { return format( "Could not find valid factory method [%s] in class [%s] but found the following invalid candidates: %s", factoryMethodName, clazz.getName(), candidates); } // Otherwise, report that we didn't find anything. return format("Could not find factory method [%s] in class [%s]", factoryMethodName, clazz.getName()); }); Preconditions.condition(factoryMethods.size() == 1, () -> format("%d factory methods named [%s] were found in class [%s]: %s", factoryMethods.size(), factoryMethodName, clazz.getName(), factoryMethods)); return factoryMethods.get(0); } private static boolean isTestMethod(Method candidate) { return isAnnotated(candidate, Test.class) || isAnnotated(candidate, TestTemplate.class) || isAnnotated(candidate, TestFactory.class); } private static Class loadRequiredClass(String className, ClassLoader classLoader) { return ReflectionUtils.tryToLoadClass(className, classLoader).getOrThrow( cause -> new JUnitException(format("Could not load class [%s]", className), cause)); } private static Method validateFactoryMethod(Method factoryMethod, Object testInstance) { Preconditions.condition( factoryMethod.getDeclaringClass().isInstance(testInstance) || ReflectionUtils.isStatic(factoryMethod), () -> format("Method '%s' must be static: local factory methods must be static " + "unless the PER_CLASS @TestInstance lifecycle mode is used; " + "external factory methods must always be static.", factoryMethod.toGenericString())); return factoryMethod; } private static Arguments toArguments(Object item) { // Nothing to do except cast. if (item instanceof Arguments) { return (Arguments) item; } // Pass all multidimensional arrays "as is", in contrast to Object[]. // See https://github.com/junit-team/junit5/issues/1665 if (ReflectionUtils.isMultidimensionalArray(item)) { return arguments(item); } // Special treatment for one-dimensional reference arrays. // See https://github.com/junit-team/junit5/issues/1665 if (item instanceof Object[]) { return arguments((Object[]) item); } // Pass everything else "as is". return arguments(item); } } MethodSource.java000066400000000000000000000154071455764576500336700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.junit.jupiter.params.ParameterizedTest; /** * {@code @MethodSource} is an {@link ArgumentsSource} which provides access * to values returned from {@linkplain #value() factory methods} of the class in * which this annotation is declared or from static factory methods in external * classes referenced by fully qualified method name. * *

Each factory method must generate a stream of arguments, * and each set of "arguments" within the "stream" will be provided as the physical * arguments for individual invocations of the annotated * {@link ParameterizedTest @ParameterizedTest} method. Generally speaking this * translates to a {@link java.util.stream.Stream Stream} of {@link Arguments} * (i.e., {@code Stream}); however, the actual concrete return type * can take on many forms. In this context, a "stream" is anything that JUnit * can reliably convert into a {@code Stream}, such as * {@link java.util.stream.Stream Stream}, * {@link java.util.stream.DoubleStream DoubleStream}, * {@link java.util.stream.LongStream LongStream}, * {@link java.util.stream.IntStream IntStream}, * {@link java.util.Collection Collection}, * {@link java.util.Iterator Iterator}, * {@link Iterable}, an array of objects, or an array of primitives. Each set of * "arguments" within the "stream" can be supplied as an instance of * {@link Arguments}, an array of objects (e.g., {@code Object[]}, * {@code String[]}, etc.), or a single value if the parameterized test * method accepts a single argument. * *

Please note that a one-dimensional array of objects supplied as a set of * "arguments" will be handled differently than other types of arguments. * Specifically, all of the elements of a one-dimensional array of objects will * be passed as individual physical arguments to the {@code @ParameterizedTest} * method. This behavior can be seen in the table below for the * {@code static Stream factory()} method: the {@code @ParameterizedTest} * method accepts individual {@code String} and {@code int} arguments rather than * a single {@code Object[]} array. In contrast, any multidimensional array * supplied as a set of "arguments" will be passed as a single physical argument * to the {@code @ParameterizedTest} method without modification. This behavior * can be seen in the table below for the {@code static Stream factory()} * and {@code static Stream factory()} methods: the * {@code @ParameterizedTest} methods for those factories accept individual * {@code int[][]} and {@code Object[][]} arguments, respectively. * *

Examples

* *

The following table displays compatible method signatures for parameterized * test methods and their corresponding factory methods. * * * * * * * * * * * * * * * * * *
Compatible method signatures and factory methods
{@code @ParameterizedTest} methodFactory method
{@code void test(int)}{@code static int[] factory()}
{@code void test(int)}{@code static IntStream factory()}
{@code void test(String)}{@code static String[] factory()}
{@code void test(String)}{@code static List factory()}
{@code void test(String)}{@code static Stream factory()}
{@code void test(String, String)}{@code static String[][] factory()}
{@code void test(String, int)}{@code static Object[][] factory()}
{@code void test(String, int)}{@code static Stream factory()}
{@code void test(String, int)}{@code static Stream factory()}
{@code void test(int[])}{@code static int[][] factory()}
{@code void test(int[])}{@code static Stream factory()}
{@code void test(int[][])}{@code static Stream factory()}
{@code void test(Object[][])}{@code static Stream factory()}
* *

Factory methods within the test class must be {@code static} unless the * {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS} * test instance lifecycle mode is used; whereas, factory methods in external * classes must always be {@code static}. * *

Factory methods can declare parameters, which will be provided by registered * implementations of {@link org.junit.jupiter.api.extension.ParameterResolver}. * * @since 5.0 * @see Arguments * @see ArgumentsSource * @see ParameterizedTest * @see org.junit.jupiter.api.TestInstance */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(MethodArgumentsProvider.class) @SuppressWarnings("exports") public @interface MethodSource { /** * The names of factory methods within the test class or in external classes * to use as sources for arguments. * *

Factory methods in external classes must be referenced by * fully-qualified method name — for example, * {@code "com.example.StringsProviders#blankStrings"} or * {@code "com.example.TopLevelClass$NestedClass#classMethod"} for a factory * method in a static nested class. * *

If a factory method accepts arguments that are provided by a * {@link org.junit.jupiter.api.extension.ParameterResolver ParameterResolver}, * you can supply the formal parameter list in the qualified method name to * disambiguate between overloaded variants of the factory method. For example, * {@code "blankStrings(int)"} for a local qualified method name or * {@code "com.example.StringsProviders#blankStrings(int)"} for a fully-qualified * method name. * *

If no factory method names are declared, a method within the test class * that has the same name as the test method will be used as the factory * method by default. * *

For further information, see the {@linkplain MethodSource class-level Javadoc}. */ String[] value() default ""; } NullAndEmptySource.java000066400000000000000000000024671455764576500350260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @NullAndEmptySource} is a composed annotation that combines * the functionality of {@link NullSource @NullSource} and * {@link EmptySource @EmptySource}. * *

Annotating a {@code @ParameterizedTest} method with * {@code @NullAndEmptySource} is equivalent to annotating the method with * {@code @NullSource} and {@code @EmptySource}. * * @since 5.4 * @see org.junit.jupiter.params.ParameterizedTest * @see NullSource * @see EmptySource */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @NullSource @EmptySource public @interface NullAndEmptySource { } NullArgumentsProvider.java000066400000000000000000000022761455764576500356020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.lang.reflect.Method; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.util.Preconditions; /** * @since 5.4 * @see NullSource */ class NullArgumentsProvider implements ArgumentsProvider { private static final Arguments nullArguments = arguments(new Object[] { null }); @Override public Stream provideArguments(ExtensionContext context) { Method testMethod = context.getRequiredTestMethod(); Preconditions.condition(testMethod.getParameterCount() > 0, () -> String.format( "@NullSource cannot provide a null argument to method [%s]: the method does not declare any formal parameters.", testMethod.toGenericString())); return Stream.of(nullArguments); } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullEnum.java000066400000000000000000000012111455764576500330710ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; /** * Dummy enum class used as default value for optional attributes of * annotations. * * @since 5.6 * @see EnumSource#value() */ @API(status = INTERNAL, since = "5.7") public enum NullEnum { } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullSource.java000066400000000000000000000027031455764576500334340ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @NullSource} is an {@link ArgumentsSource} which provides a single * {@code null} argument to the annotated {@code @ParameterizedTest} method. * *

Note that {@code @NullSource} cannot be used for an argument that has * a primitive type, unless the argument is converted to a corresponding wrapper * type with an {@link org.junit.jupiter.params.converter.ArgumentConverter}. * * @since 5.4 * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest * @see EmptySource * @see NullAndEmptySource */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(NullArgumentsProvider.class) @SuppressWarnings("exports") public @interface NullSource { } ValueArgumentsProvider.java000066400000000000000000000035271455764576500357440ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.util.stream.Collectors.toList; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.util.Preconditions; /** * @since 5.0 */ class ValueArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override protected Stream provideArguments(ExtensionContext context, ValueSource valueSource) { Object[] arguments = getArgumentsFromSource(valueSource); return Arrays.stream(arguments).map(Arguments::of); } private Object[] getArgumentsFromSource(ValueSource valueSource) { // @formatter:off List arrays = Stream.of( valueSource.shorts(), valueSource.bytes(), valueSource.ints(), valueSource.longs(), valueSource.floats(), valueSource.doubles(), valueSource.chars(), valueSource.booleans(), valueSource.strings(), valueSource.classes() ) .filter(array -> Array.getLength(array) > 0) .collect(toList()); // @formatter:on Preconditions.condition(arrays.size() == 1, () -> "Exactly one type of input must be provided in the @" + ValueSource.class.getSimpleName() + " annotation, but there were " + arrays.size()); Object originalArray = arrays.get(0); return IntStream.range(0, Array.getLength(originalArray)) // .mapToObj(index -> Array.get(originalArray, index)) // .toArray(); } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSource.java000066400000000000000000000055521455764576500336030ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ValueSource} is an {@link ArgumentsSource} which provides access to * an array of literal values. * *

Supported types include {@link #shorts}, {@link #bytes}, {@link #ints}, * {@link #longs}, {@link #floats}, {@link #doubles}, {@link #chars}, * {@link #booleans}, {@link #strings}, and {@link #classes}. Note, however, * that only one of the supported types may be specified per * {@code @ValueSource} declaration. * *

The supplied literal values will be provided as arguments to the * annotated {@code @ParameterizedTest} method. * * @since 5.0 * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.ParameterizedTest */ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(ValueArgumentsProvider.class) @SuppressWarnings("exports") public @interface ValueSource { /** * The {@code short} values to use as sources of arguments; must not be empty. * * @since 5.1 */ short[] shorts() default {}; /** * The {@code byte} values to use as sources of arguments; must not be empty. * * @since 5.1 */ byte[] bytes() default {}; /** * The {@code int} values to use as sources of arguments; must not be empty. */ int[] ints() default {}; /** * The {@code long} values to use as sources of arguments; must not be empty. */ long[] longs() default {}; /** * The {@code float} values to use as sources of arguments; must not be empty. * * @since 5.1 */ float[] floats() default {}; /** * The {@code double} values to use as sources of arguments; must not be empty. */ double[] doubles() default {}; /** * The {@code char} values to use as sources of arguments; must not be empty. * * @since 5.1 */ char[] chars() default {}; /** * The {@code boolean} values to use as sources of arguments; must not be empty. * * @since 5.5 */ boolean[] booleans() default {}; /** * The {@link String} values to use as sources of arguments; must not be empty. */ String[] strings() default {}; /** * The {@link Class} values to use as sources of arguments; must not be empty. * * @since 5.1 */ Class[] classes() default {}; } package-info.java000066400000000000000000000004151455764576500336040ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/** * {@link org.junit.jupiter.params.provider.ArgumentsProvider ArgumentsProvider} * implementations and their corresponding * {@link org.junit.jupiter.params.provider.ArgumentsSource ArgumentsSource} * annotations. */ package org.junit.jupiter.params.provider; junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/000077500000000000000000000000001455764576500303565ustar00rootroot00000000000000AnnotationConsumer.java000066400000000000000000000021311455764576500347650ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.support; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; import java.util.function.Consumer; import org.apiguardian.api.API; /** * {@code AnnotationConsumer} is a {@linkplain FunctionalInterface functional * interface} for consuming annotations. * *

It is typically implemented by implementations of * {@link org.junit.jupiter.params.provider.ArgumentsProvider ArgumentsProvider} * and {@link org.junit.jupiter.params.converter.ArgumentConverter ArgumentConverter} * in order to signal that they can {@link #accept accept} a certain annotation. * * @since 5.0 */ @FunctionalInterface @API(status = STABLE, since = "5.7") public interface AnnotationConsumer extends Consumer { } AnnotationConsumerInitializer.java000066400000000000000000000101761455764576500372010ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.support; import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.List; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.AnnotationUtils; /** * {@code AnnotationConsumerInitializer} is an internal helper class for * initializing {@link AnnotationConsumer AnnotationConsumers}. * * @since 5.0 */ @API(status = INTERNAL, since = "5.0") public final class AnnotationConsumerInitializer { private static final List annotationConsumingMethodSignatures = asList( // new AnnotationConsumingMethodSignature("accept", 1, 0), // new AnnotationConsumingMethodSignature("provideArguments", 2, 1), // new AnnotationConsumingMethodSignature("convert", 3, 2)); private AnnotationConsumerInitializer() { /* no-op */ } @SuppressWarnings({ "unchecked", "rawtypes" }) public static T initialize(AnnotatedElement annotatedElement, T annotationConsumerInstance) { if (annotationConsumerInstance instanceof AnnotationConsumer) { Class annotationType = findConsumedAnnotationType(annotationConsumerInstance); Annotation annotation = AnnotationUtils.findAnnotation(annotatedElement, annotationType) // .orElseThrow(() -> new JUnitException(annotationConsumerInstance.getClass().getName() + " must be used with an annotation of type " + annotationType.getName())); initializeAnnotationConsumer((AnnotationConsumer) annotationConsumerInstance, annotation); } return annotationConsumerInstance; } private static Class findConsumedAnnotationType(T annotationConsumerInstance) { Predicate consumesAnnotation = annotationConsumingMethodSignatures.stream() // .map(signature -> (Predicate) signature::isMatchingWith) // .reduce(method -> false, Predicate::or); Method method = findMethods(annotationConsumerInstance.getClass(), consumesAnnotation, BOTTOM_UP).get(0); return getAnnotationType(method); } @SuppressWarnings("unchecked") private static Class getAnnotationType(Method method) { int annotationIndex = annotationConsumingMethodSignatures.stream() // .filter(signature -> signature.isMatchingWith(method)) // .findFirst() // .map(AnnotationConsumingMethodSignature::getAnnotationParameterIndex) // .orElse(0); return (Class) method.getParameterTypes()[annotationIndex]; } private static void initializeAnnotationConsumer(AnnotationConsumer instance, A annotation) { try { instance.accept(annotation); } catch (Exception ex) { throw new JUnitException("Failed to initialize AnnotationConsumer: " + instance, ex); } } private static class AnnotationConsumingMethodSignature { private final String methodName; private final int parameterCount; private final int annotationParameterIndex; AnnotationConsumingMethodSignature(String methodName, int parameterCount, int annotationParameterIndex) { this.methodName = methodName; this.parameterCount = parameterCount; this.annotationParameterIndex = annotationParameterIndex; } boolean isMatchingWith(Method method) { return method.getName().equals(methodName) // && method.getParameterCount() == parameterCount // && method.getParameterTypes()[annotationParameterIndex].isAnnotation(); } int getAnnotationParameterIndex() { return annotationParameterIndex; } } } junit5-r5.10.2/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/package-info.java000066400000000000000000000004121455764576500335420ustar00rootroot00000000000000/** * Support classes for building * {@linkplain org.junit.jupiter.params.provider.ArgumentsProvider providers} * and * {@linkplain org.junit.jupiter.params.converter.ArgumentConverter converters} * for arguments. */ package org.junit.jupiter.params.support; junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/000077500000000000000000000000001455764576500223345ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/000077500000000000000000000000001455764576500231235ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/junit/000077500000000000000000000000001455764576500242545ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/000077500000000000000000000000001455764576500257365ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/000077500000000000000000000000001455764576500272215ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/000077500000000000000000000000001455764576500313435ustar00rootroot00000000000000ArgumentsAccessor.kt000066400000000000000000000020001455764576500352440ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ @file:API(status = API.Status.STABLE, since = "5.7") package org.junit.jupiter.params.aggregator import org.apiguardian.api.API /** * Get the value of the argument at the given index as an instance of the * reified type. * * @param index the index of the argument to get; must be greater than or * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} * @since 5.3 * @receiver[ArgumentsAccessor] * @see ArgumentsAccessor.get(Int, Class!) */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER") // method is in fact not shadowed due to reified type inline fun ArgumentsAccessor.get(index: Int): T = this.get(index, T::class.java) junit5-r5.10.2/junit-jupiter-params/src/module/000077500000000000000000000000001455764576500213755ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/module/org.junit.jupiter.params/000077500000000000000000000000001455764576500262575ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/module/org.junit.jupiter.params/module-info.java000066400000000000000000000017411455764576500313430ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * JUnit Jupiter extension for parameterized tests. * * @since 5.0 */ module org.junit.jupiter.params { requires static transitive org.apiguardian.api; requires transitive org.junit.jupiter.api; requires transitive org.junit.platform.commons; exports org.junit.jupiter.params; exports org.junit.jupiter.params.aggregator; exports org.junit.jupiter.params.converter; exports org.junit.jupiter.params.provider; exports org.junit.jupiter.params.support; opens org.junit.jupiter.params to org.junit.platform.commons; opens org.junit.jupiter.params.converter to org.junit.platform.commons; opens org.junit.jupiter.params.provider to org.junit.platform.commons; } junit5-r5.10.2/junit-jupiter-params/src/test/000077500000000000000000000000001455764576500210675ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/000077500000000000000000000000001455764576500220105ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/000077500000000000000000000000001455764576500225775ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/000077500000000000000000000000001455764576500237305ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/000077500000000000000000000000001455764576500254125ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/000077500000000000000000000000001455764576500266755ustar00rootroot00000000000000ParameterizedTestExtensionTests.java000066400000000000000000000261711455764576500360440ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.params.ParameterizedTestExtension.arguments; import java.io.FileNotFoundException; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.engine.execution.NamespaceAwareStore; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; /** * Unit tests for {@link ParameterizedTestExtension}. * * @since 5.0 */ class ParameterizedTestExtensionTests { private final ParameterizedTestExtension parameterizedTestExtension = new ParameterizedTestExtension(); static boolean streamWasClosed = false; @Test void supportsReturnsFalseForMissingTestMethod() { var extensionContextWithoutTestMethod = getExtensionContextReturningSingleMethod(new TestCaseWithoutMethod()); assertFalse(this.parameterizedTestExtension.supportsTestTemplate(extensionContextWithoutTestMethod)); } @Test void supportsReturnsFalseForTestMethodWithoutParameterizedTestAnnotation() { var extensionContextWithUnAnnotatedTestMethod = getExtensionContextReturningSingleMethod( new TestCaseWithMethod()); assertFalse(this.parameterizedTestExtension.supportsTestTemplate(extensionContextWithUnAnnotatedTestMethod)); } @Test void supportsReturnsTrueForTestMethodWithParameterizedTestAnnotation() { var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( new TestCaseWithAnnotatedMethod()); assertTrue(this.parameterizedTestExtension.supportsTestTemplate(extensionContextWithAnnotatedTestMethod)); } @Test void streamsReturnedByProvidersAreClosedWhenCallingProvide() { var extensionContext = getExtensionContextReturningSingleMethod( new ArgumentsProviderWithCloseHandlerTestCase()); // we need to call supportsTestTemplate() first, because it creates and // puts the ParameterizedTestMethodContext into the Store this.parameterizedTestExtension.supportsTestTemplate(extensionContext); var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts(extensionContext); assertFalse(streamWasClosed); // cause the stream to be evaluated stream.count(); assertTrue(streamWasClosed); } @Test void emptyDisplayNameIsIllegal() { var extensionContext = getExtensionContextReturningSingleMethod(new EmptyDisplayNameProviderTestCase()); assertThrows(PreconditionViolationException.class, () -> this.parameterizedTestExtension.provideTestTemplateInvocationContexts(extensionContext)); } @Test void defaultDisplayNameWithEmptyStringInConfigurationIsIllegal() { AtomicInteger invocations = new AtomicInteger(); Function> configurationSupplier = key -> { if (key.equals(ParameterizedTestExtension.DISPLAY_NAME_PATTERN_KEY)) { invocations.incrementAndGet(); return Optional.of(""); } else { return Optional.empty(); } }; var extensionContext = getExtensionContextReturningSingleMethod(new DefaultDisplayNameProviderTestCase(), configurationSupplier); assertThrows(PreconditionViolationException.class, () -> this.parameterizedTestExtension.provideTestTemplateInvocationContexts(extensionContext)); assertEquals(1, invocations.get()); } @Test void argumentsRethrowsOriginalExceptionFromProviderAsUncheckedException() { ArgumentsProvider failingProvider = (context) -> { throw new FileNotFoundException("a message"); }; var exception = assertThrows(FileNotFoundException.class, () -> arguments(failingProvider, null)); assertEquals("a message", exception.getMessage()); } @Test void throwsExceptionWhenParameterizedTestIsNotInvokedAtLeastOnce() { var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( new TestCaseWithAnnotatedMethod()); var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts( extensionContextWithAnnotatedTestMethod); // cause the stream to be evaluated stream.toArray(); var exception = assertThrows(JUnitException.class, stream::close); assertThat(exception).hasMessage( "Configuration error: You must configure at least one set of arguments for this @ParameterizedTest"); } @Test void throwsExceptionWhenArgumentsProviderIsNotStatic() { var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( new NonStaticArgumentsProviderTestCase()); var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts( extensionContextWithAnnotatedTestMethod); var exception = assertThrows(JUnitException.class, stream::toArray); assertArgumentsProviderInstantiationException(exception, NonStaticArgumentsProvider.class); } @Test void throwsExceptionWhenArgumentsProviderDoesNotContainNoArgumentConstructor() { var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( new MissingNoArgumentsConstructorArgumentsProviderTestCase()); var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts( extensionContextWithAnnotatedTestMethod); var exception = assertThrows(JUnitException.class, stream::toArray); assertArgumentsProviderInstantiationException(exception, MissingNoArgumentsConstructorArgumentsProvider.class); } private void assertArgumentsProviderInstantiationException(JUnitException exception, Class clazz) { assertThat(exception).hasMessage( String.format("Failed to find a no-argument constructor for ArgumentsProvider [%s]. " + "Please ensure that a no-argument constructor exists and " + "that the class is either a top-level class or a static nested class", clazz.getName())); } private ExtensionContext getExtensionContextReturningSingleMethod(Object testCase) { return getExtensionContextReturningSingleMethod(testCase, ignored -> Optional.empty()); } private ExtensionContext getExtensionContextReturningSingleMethod(Object testCase, Function> configurationSupplier) { // @formatter:off var optional = Arrays.stream(testCase.getClass().getDeclaredMethods()) .filter(method -> method.getName().equals("method")) .findFirst(); // @formatter:on return new ExtensionContext() { private final NamespacedHierarchicalStore store = new NamespacedHierarchicalStore<>(null); @Override public Optional getTestMethod() { return optional; } @Override public Optional getParent() { return Optional.empty(); } @Override public ExtensionContext getRoot() { return this; } @Override public String getUniqueId() { return null; } @Override public String getDisplayName() { return null; } @Override public Set getTags() { return null; } @Override public Optional getElement() { return Optional.empty(); } @Override public Optional> getTestClass() { return Optional.empty(); } @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); } @Override public java.util.Optional getTestInstance() { return Optional.empty(); } @Override public Optional getTestInstances() { return Optional.empty(); } @Override public Optional getExecutionException() { return Optional.empty(); } @Override public Optional getConfigurationParameter(String key) { return configurationSupplier.apply(key); } @Override public Optional getConfigurationParameter(String key, Function transformer) { return configurationSupplier.apply(key).map(transformer); } @Override public void publishReportEntry(Map map) { } @Override public Store getStore(Namespace namespace) { return new NamespaceAwareStore(store, namespace); } @Override public ExecutionMode getExecutionMode() { return ExecutionMode.SAME_THREAD; } @Override public ExecutableInvoker getExecutableInvoker() { return null; } }; } static class TestCaseWithoutMethod { } static class TestCaseWithMethod { void method() { } } static class TestCaseWithAnnotatedMethod { @ParameterizedTest void method() { } } static class ArgumentsProviderWithCloseHandlerTestCase { @ParameterizedTest @ArgumentsSource(ArgumentsProviderWithCloseHandler.class) void method(String parameter) { } } static class ArgumentsProviderWithCloseHandler implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { var argumentsStream = Stream.of("foo", "bar").map(Arguments::of); return argumentsStream.onClose(() -> streamWasClosed = true); } } static class NonStaticArgumentsProviderTestCase { @ParameterizedTest @ArgumentsSource(NonStaticArgumentsProvider.class) void method() { } } class NonStaticArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { return null; } } static class MissingNoArgumentsConstructorArgumentsProviderTestCase { @ParameterizedTest @ArgumentsSource(MissingNoArgumentsConstructorArgumentsProvider.class) void method() { } } static class EmptyDisplayNameProviderTestCase { @ParameterizedTest(name = "") @ArgumentsSource(MissingNoArgumentsConstructorArgumentsProvider.class) void method() { } } static class DefaultDisplayNameProviderTestCase { @ParameterizedTest @ArgumentsSource(MissingNoArgumentsConstructorArgumentsProvider.class) void method() { } } static class MissingNoArgumentsConstructorArgumentsProvider implements ArgumentsProvider { MissingNoArgumentsConstructorArgumentsProvider(String parameter) { } @Override public Stream provideArguments(ExtensionContext context) { return null; } } } ParameterizedTestIntegrationTests.java000066400000000000000000001545341455764576500363600ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.within; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.Named.named; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.appendTestTemplateInvocationSegment; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestTemplateMethod; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.testkit.engine.EventConditions.abortedWithReason; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.params.aggregator.AggregateWith; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.aggregator.ArgumentsAggregationException; import org.junit.jupiter.params.aggregator.ArgumentsAggregator; import org.junit.jupiter.params.converter.ArgumentConversionException; import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.jupiter.params.provider.CsvFileSource; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.EmptySource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Event; import org.opentest4j.TestAbortedException; /** * @since 5.0 */ class ParameterizedTestIntegrationTests { @ParameterizedTest @CsvSource(textBlock = """ apple, True banana, true lemon, false kumquat, FALSE """) void sweetFruit(String fruit, Boolean sweet) { switch (fruit) { case "apple" -> assertThat(sweet).isTrue(); case "banana" -> assertThat(sweet).isTrue(); case "lemon" -> assertThat(sweet).isFalse(); case "kumquat" -> assertThat(sweet).isFalse(); default -> fail("Unexpected fruit : " + fruit); } } @ParameterizedTest @CsvSource(nullValues = "null", textBlock = """ apple, True banana, true lemon, false kumquat, null """) void sweetFruitWithNullableBoolean(String fruit, Boolean sweet) { switch (fruit) { case "apple" -> assertThat(sweet).isTrue(); case "banana" -> assertThat(sweet).isTrue(); case "lemon" -> assertThat(sweet).isFalse(); case "kumquat" -> assertThat(sweet).isNull(); // null --> null default -> fail("Unexpected fruit : " + fruit); } } @ParameterizedTest @CsvSource(quoteCharacter = '"', textBlock = """ # This is a comment preceded by multiple opening blank lines. apple, 1 banana, 2 # This is a comment pointing out that the next line contains multiple explicit newlines in quoted text. "lemon \s \s lime", 0xF1 # The next line is a blank line in the middle of the CSV rows. strawberry, 700_000 # This is a comment followed by 2 closing blank line. """) void executesLinesFromTextBlock(String fruit, int rank) { switch (fruit) { case "apple" -> assertThat(rank).isEqualTo(1); case "banana" -> assertThat(rank).isEqualTo(2); case "lemon \n\n\n lime" -> assertThat(rank).isEqualTo(241); case "strawberry" -> assertThat(rank).isEqualTo(700_000); default -> fail("Unexpected fruit : " + fruit); } } @ParameterizedTest(name = "[{index}] {arguments}") @CsvSource(delimiter = '|', useHeadersInDisplayName = true, nullValues = "NIL", textBlock = """ #--------------------------------- FRUIT | RANK #--------------------------------- apple | 1 #--------------------------------- banana | 2 #--------------------------------- cherry | 3.14159265358979323846 #--------------------------------- | 0 #--------------------------------- NIL | 0 #--------------------------------- """) void executesLinesFromTextBlockUsingTableFormatAndHeadersAndNullValues(String fruit, double rank, TestInfo testInfo) { assertFruitTable(fruit, rank, testInfo); } @ParameterizedTest(name = "[{index}] {arguments}") @CsvFileSource(resources = "two-column-with-headers.csv", delimiter = '|', useHeadersInDisplayName = true, nullValues = "NIL") void executesLinesFromClasspathResourceUsingTableFormatAndHeadersAndNullValues(String fruit, double rank, TestInfo testInfo) { assertFruitTable(fruit, rank, testInfo); } private void assertFruitTable(String fruit, double rank, TestInfo testInfo) { String displayName = testInfo.getDisplayName(); if (fruit == null) { assertThat(rank).isEqualTo(0); assertThat(displayName).matches("\\[(4|5)\\] FRUIT = null, RANK = 0"); return; } switch (fruit) { case "apple" -> { assertThat(rank).isEqualTo(1); assertThat(displayName).isEqualTo("[1] FRUIT = apple, RANK = 1"); } case "banana" -> { assertThat(rank).isEqualTo(2); assertThat(displayName).isEqualTo("[2] FRUIT = banana, RANK = 2"); } case "cherry" -> { assertThat(rank).isCloseTo(Math.PI, within(0.0)); assertThat(displayName).isEqualTo("[3] FRUIT = cherry, RANK = 3.14159265358979323846"); } default -> fail("Unexpected fruit : " + fruit); } } @Test void executesWithSingleArgumentsProviderWithMultipleInvocations() { var results = execute("testWithTwoSingleStringArgumentsProvider", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @Test void executesWithCsvSource() { var results = execute("testWithCsvSource", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @Test void executesWithCustomName() { var results = execute("testWithCustomName", String.class, int.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("foo and 23"), finishedWithFailure(message("foo, 23")))) // .haveExactly(1, event(test(), displayName("bar and 42"), finishedWithFailure(message("bar, 42")))); } /** * @since 5.2 */ @Test void executesWithPrimitiveWideningConversion() { var results = execute("testWithPrimitiveWideningConversion", double.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] num=1"), finishedWithFailure(message("num: 1.0")))) // .haveExactly(1, event(test(), displayName("[2] num=2"), finishedWithFailure(message("num: 2.0")))); } /** * @since 5.1 */ @Test void executesWithImplicitGenericConverter() { var results = execute("testWithImplicitGenericConverter", Book.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] book=book 1"), finishedWithFailure(message("book 1")))) // .haveExactly(1, event(test(), displayName("[2] book=book 2"), finishedWithFailure(message("book 2")))); } @Test void legacyReportingNames() { var results = execute("testWithCustomName", String.class, int.class); // @formatter:off var legacyReportingNames = results.testEvents().dynamicallyRegistered() .map(Event::getTestDescriptor) .map(TestDescriptor::getLegacyReportingName); // @formatter:on assertThat(legacyReportingNames).containsExactly("testWithCustomName(String, int)[1]", "testWithCustomName(String, int)[2]"); } @Test void executesWithExplicitConverter() { var results = execute("testWithExplicitConverter", int.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] length=O"), finishedWithFailure(message("length: 1")))) // .haveExactly(1, event(test(), displayName("[2] length=XXX"), finishedWithFailure(message("length: 3")))); } @Test void executesWithAggregator() { var results = execute("testWithAggregator", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] ab, cd"), finishedWithFailure(message("concatenation: abcd")))) // .haveExactly(1, event(test(), displayName("[2] ef, gh"), finishedWithFailure(message("concatenation: efgh")))); } @Test void executesWithIgnoreLeadingAndTrailingSetToFalseForCsvSource() { var results = execute("testWithIgnoreLeadingAndTrailingWhitespaceSetToFalseForCsvSource", String.class, String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: ' ab ', ' cd'")))) // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ef ', 'gh'")))); } @Test void executesWithIgnoreLeadingAndTrailingSetToTrueForCsvSource() { var results = execute("testWithIgnoreLeadingAndTrailingWhitespaceSetToTrueForCsvSource", String.class, String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ab', 'cd'")))) // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ef', 'gh'")))); } @Test void executesWithIgnoreLeadingAndTrailingSetToFalseForCsvFileSource() { var results = execute("testWithIgnoreLeadingAndTrailingWhitespaceSetToFalseForCsvFileSource", String.class, String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: ' ab ', ' cd'")))) // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ef ', 'gh'")))); } @Test void executesWithIgnoreLeadingAndTrailingSetToTrueForCsvFileSource() { var results = execute("testWithIgnoreLeadingAndTrailingWhitespaceSetToTrueForCsvFileSource", String.class, String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ab', 'cd'")))) // .haveExactly(1, event(test(), finishedWithFailure(message("arguments: 'ef', 'gh'")))); } @Test void failsContainerOnEmptyName() { var results = execute("testWithEmptyName", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(container(), displayName("testWithEmptyName(String)"), // finishedWithFailure(message(msg -> msg.contains("must be declared with a non-empty name"))))); } @Test void reportsExceptionForErroneousConverter() { var results = execute("testWithErroneousConverter", Object.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedWithFailure(instanceOf(ParameterResolutionException.class), // message("Error converting parameter at index 0: something went horribly wrong")))); } @Test void executesLifecycleMethods() { // reset static collections LifecycleTestCase.lifecycleEvents.clear(); LifecycleTestCase.testMethods.clear(); var results = execute(selectClass(LifecycleTestCase.class)); results.allEvents().assertThatEvents() // .haveExactly(1, event(test("test1"), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test("test1"), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); List testMethods = new ArrayList<>(LifecycleTestCase.testMethods); // @formatter:off assertThat(LifecycleTestCase.lifecycleEvents).containsExactly( "beforeAll:ParameterizedTestIntegrationTests$LifecycleTestCase", "providerMethod", "constructor:ParameterizedTestIntegrationTests$LifecycleTestCase", "beforeEach:[1] argument=foo", testMethods.get(0) + ":[1] argument=foo", "afterEach:[1] argument=foo", "constructor:ParameterizedTestIntegrationTests$LifecycleTestCase", "beforeEach:[2] argument=bar", testMethods.get(0) + ":[2] argument=bar", "afterEach:[2] argument=bar", "providerMethod", "constructor:ParameterizedTestIntegrationTests$LifecycleTestCase", "beforeEach:[1] argument=foo", testMethods.get(1) + ":[1] argument=foo", "afterEach:[1] argument=foo", "constructor:ParameterizedTestIntegrationTests$LifecycleTestCase", "beforeEach:[2] argument=bar", testMethods.get(1) + ":[2] argument=bar", "afterEach:[2] argument=bar", "afterAll:ParameterizedTestIntegrationTests$LifecycleTestCase"); // @formatter:on } @Test void truncatesArgumentsThatExceedMaxLength() { var results = EngineTestKit.engine(new JupiterTestEngine()) // .configurationParameter(ParameterizedTestExtension.ARGUMENT_MAX_LENGTH_KEY, "2") // .selectors(selectMethod(TestCase.class, "testWithCsvSource", String.class.getName())) // .execute(); results.testEvents().assertThatEvents() // .haveExactly(1, event(displayName("[1] argument=f…"), started())) // .haveExactly(1, event(displayName("[2] argument=b…"), started())); } @Test void displayNamePatternFromConfiguration() { var results = EngineTestKit.engine(new JupiterTestEngine()) // .configurationParameter(ParameterizedTestExtension.DISPLAY_NAME_PATTERN_KEY, "{index}") // .selectors(selectMethod(TestCase.class, "testWithCsvSource", String.class.getName())) // .execute(); results.testEvents().assertThatEvents() // .haveExactly(1, event(displayName("1"), started())) // .haveExactly(1, event(displayName("2"), started())); } private EngineExecutionResults execute(DiscoverySelector... selectors) { return EngineTestKit.engine(new JupiterTestEngine()).selectors(selectors).execute(); } private EngineExecutionResults execute(Class testClass, String methodName, Class... methodParameterTypes) { return execute(selectMethod(testClass, methodName, ClassUtils.nullSafeToString(methodParameterTypes))); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return execute(TestCase.class, methodName, methodParameterTypes); } /** * @since 5.4 */ @Nested class NullSourceIntegrationTests { @Test void executesWithNullSourceForString() { var results = execute("testWithNullSourceForString", String.class); results.testEvents().failed().assertEventsMatchExactly( event(test(), displayName("[1] argument=null"), finishedWithFailure(message("null")))); } @Test void executesWithNullSourceForStringAndTestInfo() { var results = execute("testWithNullSourceForStringAndTestInfo", String.class, TestInfo.class); results.testEvents().failed().assertEventsMatchExactly( event(test(), displayName("[1] argument=null"), finishedWithFailure(message("null")))); } @Test void executesWithNullSourceForNumber() { var results = execute("testWithNullSourceForNumber", Number.class); results.testEvents().failed().assertEventsMatchExactly( event(test(), displayName("[1] argument=null"), finishedWithFailure(message("null")))); } @Test void failsWithNullSourceWithZeroFormalParameters() { var methodName = "testWithNullSourceWithZeroFormalParameters"; execute(methodName).containerEvents().failed().assertEventsMatchExactly(// event(container(methodName), // finishedWithFailure(// instanceOf(PreconditionViolationException.class), // message(msg -> msg.matches( "@NullSource cannot provide a null argument to method .+: the method does not declare any formal parameters."))))); } @Test void failsWithNullSourceForPrimitive() { var results = execute("testWithNullSourceForPrimitive", int.class); results.testEvents().failed().assertEventsMatchExactly(event(test(), displayName("[1] argument=null"), finishedWithFailure(instanceOf(ParameterResolutionException.class), message( "Error converting parameter at index 0: Cannot convert null to primitive value of type int")))); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return ParameterizedTestIntegrationTests.this.execute(NullSourceTestCase.class, methodName, methodParameterTypes); } } /** * @since 5.4 */ @Nested class EmptySourceIntegrationTests { @Test void executesWithEmptySourceForString() { var results = execute("testWithEmptySourceForString", String.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument="))); } @Test void executesWithEmptySourceForStringAndTestInfo() { var results = execute("testWithEmptySourceForStringAndTestInfo", String.class, TestInfo.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument="))); } /** * @since 5.10 */ @Test void executesWithEmptySourceForCollection() { var results = execute("testWithEmptySourceForCollection", Collection.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForList() { var results = execute("testWithEmptySourceForList", List.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } /** * @since 5.10 */ @ParameterizedTest(name = "{1}") @CsvSource(textBlock = """ testWithEmptySourceForArrayList, java.util.ArrayList testWithEmptySourceForLinkedList, java.util.LinkedList """) void executesWithEmptySourceForListSubtype(String methodName, Class parameterType) { var results = execute(methodName, parameterType); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForSet() { var results = execute("testWithEmptySourceForSet", Set.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } /** * @since 5.10 */ @ParameterizedTest(name = "{1}") @CsvSource(textBlock = """ testWithEmptySourceForSortedSet, java.util.SortedSet testWithEmptySourceForNavigableSet, java.util.NavigableSet testWithEmptySourceForHashSet, java.util.HashSet testWithEmptySourceForTreeSet, java.util.TreeSet testWithEmptySourceForLinkedHashSet, java.util.LinkedHashSet """) void executesWithEmptySourceForSetSubtype(String methodName, Class parameterType) { var results = execute(methodName, parameterType); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForMap() { var results = execute("testWithEmptySourceForMap", Map.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument={}"))); } /** * @since 5.10 */ @ParameterizedTest(name = "{1}") @CsvSource(textBlock = """ testWithEmptySourceForSortedMap, java.util.SortedMap testWithEmptySourceForNavigableMap, java.util.NavigableMap testWithEmptySourceForHashMap, java.util.HashMap testWithEmptySourceForTreeMap, java.util.TreeMap testWithEmptySourceForLinkedHashMap, java.util.LinkedHashMap """) void executesWithEmptySourceForMapSubtype(String methodName, Class parameterType) { var results = execute(methodName, parameterType); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument={}"))); } @Test void executesWithEmptySourceForOneDimensionalPrimitiveArray() { var results = execute("testWithEmptySourceForOneDimensionalPrimitiveArray", int[].class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForOneDimensionalStringArray() { var results = execute("testWithEmptySourceForOneDimensionalStringArray", String[].class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForTwoDimensionalPrimitiveArray() { var results = execute("testWithEmptySourceForTwoDimensionalPrimitiveArray", int[][].class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void executesWithEmptySourceForTwoDimensionalStringArray() { var results = execute("testWithEmptySourceForTwoDimensionalStringArray", String[][].class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } @Test void failsWithEmptySourceWithZeroFormalParameters() { var methodName = "testWithEmptySourceWithZeroFormalParameters"; execute(methodName).containerEvents().failed().assertEventsMatchExactly(// event(container(methodName), // finishedWithFailure(// instanceOf(PreconditionViolationException.class), // message(msg -> msg.matches( "@EmptySource cannot provide an empty argument to method .+: the method does not declare any formal parameters."))))); } @ParameterizedTest(name = "{1}") @CsvSource(textBlock = """ testWithEmptySourceForPrimitive, int testWithEmptySourceForUnsupportedReferenceType, java.lang.Integer """) void failsWithEmptySourceForUnsupportedType(String methodName, Class parameterType) { execute(methodName, parameterType).containerEvents().failed().assertEventsMatchExactly(// event(container(methodName), // finishedWithFailure(// instanceOf(PreconditionViolationException.class), // message(msg -> msg.matches("@EmptySource cannot provide an empty argument to method .+: \\[" + parameterType.getName() + "] is not a supported type."))// ))); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return ParameterizedTestIntegrationTests.this.execute(EmptySourceTestCase.class, methodName, methodParameterTypes); } } /** * @since 5.4 */ @Nested class NullAndEmptySourceIntegrationTests { @Test void executesWithNullAndEmptySourceForString() { var results = execute("testWithNullAndEmptySourceForString", String.class); assertNullAndEmptyString(results); } @Test void executesWithNullAndEmptySourceForStringAndTestInfo() { var results = execute("testWithNullAndEmptySourceForStringAndTestInfo", String.class, TestInfo.class); assertNullAndEmptyString(results); } @Test void executesWithNullAndEmptySourceForList() { var results = execute("testWithNullAndEmptySourceForList", List.class); assertNullAndEmpty(results); } @Test void executesWithNullAndEmptySourceForArrayList() { var results = execute("testWithNullAndEmptySourceForArrayList", ArrayList.class); assertNullAndEmpty(results); } @Test void executesWithNullAndEmptySourceForOneDimensionalPrimitiveArray() { var results = execute("testWithNullAndEmptySourceForOneDimensionalPrimitiveArray", int[].class); assertNullAndEmpty(results); } @Test void executesWithNullAndEmptySourceForTwoDimensionalStringArray() { var results = execute("testWithNullAndEmptySourceForTwoDimensionalStringArray", String[][].class); assertNullAndEmpty(results); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return ParameterizedTestIntegrationTests.this.execute(NullAndEmptySourceTestCase.class, methodName, methodParameterTypes); } private void assertNullAndEmptyString(EngineExecutionResults results) { results.testEvents().succeeded().assertEventsMatchExactly(// event(test(), displayName("[1] argument=null")), // event(test(), displayName("[2] argument="))// ); } private void assertNullAndEmpty(EngineExecutionResults results) { results.testEvents().succeeded().assertEventsMatchExactly(// event(test(), displayName("[1] argument=null")), // event(test(), displayName("[2] argument=[]"))// ); } } @Nested class MethodSourceIntegrationTests { @Test void emptyMethodSource() { execute("emptyMethodSource", String.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("empty method source")))); } /** * @since 5.3.2 */ @Test void oneDimensionalPrimitiveArray() { execute("oneDimensionalPrimitiveArray", int.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("1"))))// .haveExactly(1, event(test(), finishedWithFailure(message("2")))); } /** * @since 5.3.2 */ @Test void twoDimensionalPrimitiveArray() { execute("twoDimensionalPrimitiveArray", int[].class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("[1, 2]"))))// .haveExactly(1, event(test(), finishedWithFailure(message("[3, 4]")))); } /** * @since 5.3.2 */ @Test void oneDimensionalObjectArray() { execute("oneDimensionalObjectArray", Object.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("one"))))// .haveExactly(1, event(test(), finishedWithFailure(message("2"))))// .haveExactly(1, event(test(), finishedWithFailure(message("three")))); } /** * @since 5.3.2 */ @Test void oneDimensionalStringArray() { execute("oneDimensionalStringArray", String.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("one"))))// .haveExactly(1, event(test(), finishedWithFailure(message("two")))); } @Test void twoDimensionalObjectArray() { execute("twoDimensionalObjectArray", String.class, int.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("one:2"))))// .haveExactly(1, event(test(), finishedWithFailure(message("three:4")))); } /** * @since 5.3.2 */ @Test void twoDimensionalStringArray() { execute("twoDimensionalStringArray", String.class, String.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("one:two"))))// .haveExactly(1, event(test(), finishedWithFailure(message("three:four")))); } /** * @since 5.3.2 */ @Test void streamOfOneDimensionalPrimitiveArrays() { execute("streamOfOneDimensionalPrimitiveArrays", int[].class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("[1, 2]"))))// .haveExactly(1, event(test(), finishedWithFailure(message("[3, 4]")))); } /** * @since 5.3.2 */ @Test void streamOfTwoDimensionalPrimitiveArrays() { assertStreamOfTwoDimensionalPrimitiveArrays("streamOfTwoDimensionalPrimitiveArrays"); } /** * @since 5.3.2 */ @Test void streamOfTwoDimensionalPrimitiveArraysWrappedInObjectArrays() { assertStreamOfTwoDimensionalPrimitiveArrays("streamOfTwoDimensionalPrimitiveArraysWrappedInObjectArrays"); } /** * @since 5.3.2 */ @Test void streamOfTwoDimensionalPrimitiveArraysWrappedInArguments() { assertStreamOfTwoDimensionalPrimitiveArrays("streamOfTwoDimensionalPrimitiveArraysWrappedInArguments"); } private void assertStreamOfTwoDimensionalPrimitiveArrays(String methodName) { execute(methodName, int[][].class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("[[1, 2], [3, 4]]"))))// .haveExactly(1, event(test(), finishedWithFailure(message("[[5, 6], [7, 8]]")))); } /** * @since 5.3.2 */ @Test void streamOfOneDimensionalObjectArrays() { execute("streamOfOneDimensionalObjectArrays", String.class, int.class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("one:2"))))// .haveExactly(1, event(test(), finishedWithFailure(message("three:4")))); } /** * @since 5.3.2 */ @Test void streamOfTwoDimensionalObjectArrays() { execute("streamOfTwoDimensionalObjectArrays", Object[][].class).testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(message("[[one, 2], [three, 4]]"))))// .haveExactly(1, event(test(), finishedWithFailure(message("[[five, 6], [seven, 8]]")))); } @Test void reportsContainerWithAssumptionFailureInMethodSourceAsAborted() { execute("assumptionFailureInMethodSourceFactoryMethod", String.class).allEvents().assertThatEvents() // .haveExactly(1, event(container("test-template:assumptionFailureInMethodSourceFactoryMethod"), // abortedWithReason(instanceOf(TestAbortedException.class), message("Assumption failed: nothing to test")))); } @Test void namedParameters() { execute("namedParameters", String.class).allEvents().assertThatEvents() // .haveAtLeast(1, event(test(), displayName("cool name"), finishedWithFailure(message("parameter value")))) // .haveAtLeast(1, event(test(), displayName("default name"), finishedWithFailure(message("default name")))); } @Test void nameParametersAlias() { execute("namedParametersAlias", String.class).allEvents().assertThatEvents() // .haveAtLeast(1, event(test(), displayName("cool name"), finishedWithFailure(message("parameter value")))) // .haveAtLeast(1, event(test(), displayName("default name"), finishedWithFailure(message("default name")))); } /** * @since 5.9.1 * @see https://github.com/junit-team/junit5/issues/3001 */ @Test void duplicateMethodNames() { // It is sufficient to assert that 8 tests started and finished, because // without the fix for #3001 the 4 parameterized tests would fail. In // other words, we're not really testing the support for @RepeatedTest // and @TestFactory, but their presence also contributes to the bug // reported in #3001. ParameterizedTestIntegrationTests.this.execute(selectClass(DuplicateMethodNamesMethodSourceTestCase.class))// .testEvents()// .assertStatistics(stats -> stats.started(8).failed(0).finished(8)); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return ParameterizedTestIntegrationTests.this.execute(MethodSourceTestCase.class, methodName, methodParameterTypes); } } @Nested class UnusedArgumentsIntegrationTests { @Test void executesWithArgumentsSourceProvidingUnusedArguments() { var results = execute("testWithTwoUnusedStringArgumentsProvider", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @Test void executesWithCsvSourceContainingUnusedArguments() { var results = execute("testWithCsvSourceContainingUnusedArguments", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @Test void executesWithCsvFileSourceContainingUnusedArguments() { var results = execute("testWithCsvFileSourceContainingUnusedArguments", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @Test void executesWithMethodSourceProvidingUnusedArguments() { var results = execute("testWithMethodSourceProvidingUnusedArguments", String.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } private EngineExecutionResults execute(String methodName, Class... methodParameterTypes) { return ParameterizedTestIntegrationTests.this.execute(UnusedArgumentsTestCase.class, methodName, methodParameterTypes); } } @Test void closeAutoCloseableArgumentsAfterTest() { var results = execute("testWithAutoCloseableArgument", AutoCloseableArgument.class); results.allEvents().assertThatEvents() // .haveExactly(1, event(test(), finishedSuccessfully())); assertTrue(AutoCloseableArgument.isClosed); } @Test void executesTwoIterationsBasedOnIterationAndUniqueIdSelector() { var methodId = uniqueIdForTestTemplateMethod(TestCase.class, "testWithThreeIterations(int)"); var results = execute(selectUniqueId(appendTestTemplateInvocationSegment(methodId, 3)), selectIteration(selectMethod(TestCase.class, "testWithThreeIterations", "int"), 1)); results.allEvents().assertThatEvents() // .haveExactly(2, event(test(), finishedWithFailure())) // .haveExactly(1, event(test(), displayName("[2] argument=3"), finishedWithFailure())) // .haveExactly(1, event(test(), displayName("[3] argument=5"), finishedWithFailure())); } // ------------------------------------------------------------------------- static class TestCase { @ParameterizedTest @ArgumentsSource(TwoSingleStringArgumentsProvider.class) void testWithTwoSingleStringArgumentsProvider(String argument) { fail(argument); } @ParameterizedTest @CsvSource({ "foo", "bar" }) void testWithCsvSource(String argument) { fail(argument); } @ParameterizedTest(name = "{0} and {1}") @CsvSource({ "foo, 23", "bar, 42" }) void testWithCustomName(String argument, int i) { fail(argument + ", " + i); } @ParameterizedTest @ValueSource(shorts = { 1, 2 }) void testWithPrimitiveWideningConversion(double num) { fail("num: " + num); } @ParameterizedTest @ValueSource(strings = { "book 1", "book 2" }) void testWithImplicitGenericConverter(Book book) { fail(book.title); } @ParameterizedTest @ValueSource(strings = { "O", "XXX" }) void testWithExplicitConverter(@ConvertWith(StringLengthConverter.class) int length) { fail("length: " + length); } @ParameterizedTest(name = " \t ") @ValueSource(strings = "not important") void testWithEmptyName(String argument) { fail(argument); } @ParameterizedTest @ValueSource(ints = 42) void testWithErroneousConverter(@ConvertWith(ErroneousConverter.class) Object ignored) { fail("this should never be called"); } @ParameterizedTest @CsvSource({ "ab, cd", "ef, gh" }) void testWithAggregator(@AggregateWith(StringAggregator.class) String concatenation) { fail("concatenation: " + concatenation); } @ParameterizedTest @CsvSource(value = { " ab , cd", "ef ,gh" }, ignoreLeadingAndTrailingWhitespace = false) void testWithIgnoreLeadingAndTrailingWhitespaceSetToFalseForCsvSource(String argument1, String argument2) { fail("arguments: '" + argument1 + "', '" + argument2 + "'"); } @ParameterizedTest @CsvSource(value = { " ab , cd", "ef ,gh" }, ignoreLeadingAndTrailingWhitespace = true) void testWithIgnoreLeadingAndTrailingWhitespaceSetToTrueForCsvSource(String argument1, String argument2) { fail("arguments: '" + argument1 + "', '" + argument2 + "'"); } @ParameterizedTest @CsvFileSource(resources = "/leading-trailing-spaces.csv", ignoreLeadingAndTrailingWhitespace = false) void testWithIgnoreLeadingAndTrailingWhitespaceSetToFalseForCsvFileSource(String argument1, String argument2) { fail("arguments: '" + argument1 + "', '" + argument2 + "'"); } @ParameterizedTest @CsvFileSource(resources = "/leading-trailing-spaces.csv", ignoreLeadingAndTrailingWhitespace = true) void testWithIgnoreLeadingAndTrailingWhitespaceSetToTrueForCsvFileSource(String argument1, String argument2) { fail("arguments: '" + argument1 + "', '" + argument2 + "'"); } @ParameterizedTest @ArgumentsSource(AutoCloseableArgumentProvider.class) void testWithAutoCloseableArgument(AutoCloseableArgument autoCloseable) { assertFalse(AutoCloseableArgument.isClosed); } @ParameterizedTest @ValueSource(ints = { 2, 3, 5 }) void testWithThreeIterations(int argument) { fail("argument: " + argument); } } static class NullSourceTestCase { @ParameterizedTest @NullSource void testWithNullSourceForString(String argument) { fail(String.valueOf(argument)); } @ParameterizedTest @NullSource void testWithNullSourceForStringAndTestInfo(String argument, TestInfo testInfo) { assertThat(testInfo).isNotNull(); fail(String.valueOf(argument)); } @ParameterizedTest @NullSource void testWithNullSourceForNumber(Number argument) { fail(String.valueOf(argument)); } @ParameterizedTest @NullSource void testWithNullSourceWithZeroFormalParameters() { fail("should not have been executed"); } @ParameterizedTest @NullSource void testWithNullSourceForPrimitive(int argument) { fail("should not have been executed"); } } static class EmptySourceTestCase { @ParameterizedTest @EmptySource void testWithEmptySourceForString(String argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForStringAndTestInfo(String argument, TestInfo testInfo) { assertThat(argument).isEmpty(); assertThat(testInfo).isNotNull(); } @ParameterizedTest @EmptySource void testWithEmptySourceForCollection(Collection argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForList(List argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForArrayList(ArrayList argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForLinkedList(LinkedList argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForSet(Set argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForSortedSet(SortedSet argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForNavigableSet(NavigableSet argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForHashSet(HashSet argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForTreeSet(TreeSet argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForLinkedHashSet(LinkedHashSet argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForMap(Map argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForSortedMap(SortedMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForNavigableMap(NavigableMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForHashMap(HashMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForTreeMap(TreeMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForLinkedHashMap(LinkedHashMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForOneDimensionalPrimitiveArray(int[] argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForOneDimensionalStringArray(String[] argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForTwoDimensionalPrimitiveArray(int[][] argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceForTwoDimensionalStringArray(String[][] argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource void testWithEmptySourceWithZeroFormalParameters() { fail("should not have been executed"); } @ParameterizedTest @EmptySource void testWithEmptySourceForPrimitive(int argument) { fail("should not have been executed"); } @ParameterizedTest @EmptySource void testWithEmptySourceForUnsupportedReferenceType(Integer argument) { fail("should not have been executed"); } } static class NullAndEmptySourceTestCase { @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForString(String argument) { assertTrue(argument == null || argument.isEmpty()); } @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForStringAndTestInfo(String argument, TestInfo testInfo) { assertTrue(argument == null || argument.isEmpty()); assertThat(testInfo).isNotNull(); } @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForList(List argument) { assertTrue(argument == null || argument.isEmpty()); } @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForArrayList(ArrayList argument) { assertTrue(argument == null || argument.isEmpty()); } @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForOneDimensionalPrimitiveArray(int[] argument) { assertTrue(argument == null || argument.length == 0); } @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForTwoDimensionalStringArray(String[][] argument) { assertTrue(argument == null || argument.length == 0); } } @TestMethodOrder(OrderAnnotation.class) static class MethodSourceTestCase { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest(name = "{arguments}") @MethodSource @interface MethodSourceTest { } @MethodSourceTest void emptyMethodSource(String argument) { fail(argument); } @MethodSourceTest @Order(1) void oneDimensionalPrimitiveArray(int x) { fail("" + x); } @MethodSourceTest @Order(2) void twoDimensionalPrimitiveArray(int[] array) { fail(Arrays.toString(array)); } @MethodSourceTest @Order(3) void oneDimensionalObjectArray(Object o) { fail("" + o); } @MethodSourceTest @Order(4) void oneDimensionalStringArray(String s) { fail(s); } @MethodSourceTest @Order(5) void twoDimensionalObjectArray(String s, int x) { fail(s + ":" + x); } @MethodSourceTest @Order(6) void twoDimensionalStringArray(String s1, String s2) { fail(s1 + ":" + s2); } @MethodSourceTest @Order(7) void streamOfOneDimensionalPrimitiveArrays(int[] array) { fail(Arrays.toString(array)); } @MethodSourceTest @Order(8) void streamOfTwoDimensionalPrimitiveArrays(int[][] array) { fail(Arrays.deepToString(array)); } @MethodSourceTest @Order(9) void streamOfTwoDimensionalPrimitiveArraysWrappedInObjectArrays(int[][] array) { fail(Arrays.deepToString(array)); } @MethodSourceTest @Order(10) void streamOfTwoDimensionalPrimitiveArraysWrappedInArguments(int[][] array) { fail(Arrays.deepToString(array)); } @MethodSourceTest @Order(11) void streamOfOneDimensionalObjectArrays(String s, int x) { fail(s + ":" + x); } @MethodSourceTest @Order(12) void streamOfTwoDimensionalObjectArrays(Object[][] array) { fail(Arrays.deepToString(array)); } @MethodSourceTest @Order(13) void namedParameters(String string) { fail(string); } @MethodSourceTest @Order(14) void namedParametersAlias(String string) { fail(string); } // --------------------------------------------------------------------- static Stream emptyMethodSource() { return Stream.of(arguments("empty method source")); } static int[] oneDimensionalPrimitiveArray() { return new int[] { 1, 2 }; } static int[][] twoDimensionalPrimitiveArray() { return new int[][] { { 1, 2 }, { 3, 4 } }; } static Object[] oneDimensionalObjectArray() { return new Object[] { "one", 2, "three" }; } static Object[] oneDimensionalStringArray() { return new Object[] { "one", "two" }; } static Object[][] twoDimensionalObjectArray() { return new Object[][] { { "one", 2 }, { "three", 4 } }; } static String[][] twoDimensionalStringArray() { return new String[][] { { "one", "two" }, { "three", "four" } }; } static Stream streamOfOneDimensionalPrimitiveArrays() { return Stream.of(new int[] { 1, 2 }, new int[] { 3, 4 }); } static Stream streamOfTwoDimensionalPrimitiveArrays() { return Stream.of(new int[][] { { 1, 2 }, { 3, 4 } }, new int[][] { { 5, 6 }, { 7, 8 } }); } static Stream streamOfTwoDimensionalPrimitiveArraysWrappedInObjectArrays() { return Stream.of(new Object[] { new int[][] { { 1, 2 }, { 3, 4 } } }, new Object[] { new int[][] { { 5, 6 }, { 7, 8 } } }); } static Stream streamOfTwoDimensionalPrimitiveArraysWrappedInArguments() { return Stream.of(arguments((Object) new int[][] { { 1, 2 }, { 3, 4 } }), arguments((Object) new int[][] { { 5, 6 }, { 7, 8 } })); } static Stream streamOfOneDimensionalObjectArrays() { return Stream.of(new Object[] { "one", 2 }, new Object[] { "three", 4 }); } static Stream streamOfTwoDimensionalObjectArrays() { return Stream.of(new Object[][] { { "one", 2 }, { "three", 4 } }, new Object[][] { { "five", 6 }, { "seven", 8 } }); } static Stream namedParameters() { return Stream.of(arguments(Named.of("cool name", "parameter value")), arguments("default name")); } static Stream namedParametersAlias() { return Stream.of(arguments(named("cool name", "parameter value")), arguments("default name")); } // --------------------------------------------------------------------- @MethodSourceTest void assumptionFailureInMethodSourceFactoryMethod(String test) { } static List assumptionFailureInMethodSourceFactoryMethod() { Assumptions.assumeFalse(true, "nothing to test"); return null; } } /** * @since 5.9.1 * @see https://github.com/junit-team/junit5/issues/3001 */ static class DuplicateMethodNamesMethodSourceTestCase { @ParameterizedTest @MethodSource void test(String value) { test(1, value); } @ParameterizedTest @MethodSource("test") void anotherTest(String value) { assertTrue(test(value, 1)); } @RepeatedTest(2) void test(TestReporter testReporter) { assertNotNull(testReporter); } @TestFactory Stream test(TestInfo testInfo) { return test().map(value -> dynamicTest(value, () -> test(1, value))); } // neither a test method nor a factory method. // intentionally void. private void test(int expectedLength, String value) { assertEquals(expectedLength, value.length()); } // neither a test method nor a factory method. // intentionally non-void and also not convertible to a Stream. private boolean test(String value, int expectedLength) { return (value.length() == expectedLength); } // legitimate factory method. private static Stream test() { return Stream.of("a", "b"); } } static class UnusedArgumentsTestCase { @ParameterizedTest @ArgumentsSource(TwoUnusedStringArgumentsProvider.class) void testWithTwoUnusedStringArgumentsProvider(String argument) { fail(argument); } @ParameterizedTest @CsvSource({ "foo, unused1", "bar, unused2" }) void testWithCsvSourceContainingUnusedArguments(String argument) { fail(argument); } @ParameterizedTest @CsvFileSource(resources = "two-column.csv") void testWithCsvFileSourceContainingUnusedArguments(String argument) { fail(argument); } @ParameterizedTest @MethodSource("unusedArgumentsProviderMethod") void testWithMethodSourceProvidingUnusedArguments(String argument) { fail(argument); } static Stream unusedArgumentsProviderMethod() { return Stream.of(arguments("foo", "unused1"), arguments("bar", "unused2")); } } static class LifecycleTestCase { private static final List lifecycleEvents = new ArrayList<>(); private static final Set testMethods = new LinkedHashSet<>(); public LifecycleTestCase(TestInfo testInfo) { lifecycleEvents.add("constructor:" + testInfo.getDisplayName()); } @BeforeAll static void beforeAll(TestInfo testInfo) { lifecycleEvents.add("beforeAll:" + testInfo.getDisplayName()); } @AfterAll static void afterAll(TestInfo testInfo) { lifecycleEvents.add("afterAll:" + testInfo.getDisplayName()); } @BeforeEach void beforeEach(TestInfo testInfo) { lifecycleEvents.add("beforeEach:" + testInfo.getDisplayName()); } @AfterEach void afterEach(TestInfo testInfo) { lifecycleEvents.add("afterEach:" + testInfo.getDisplayName()); } @ParameterizedTest @MethodSource("providerMethod") void test1(String argument, TestInfo testInfo) { performTest(argument, testInfo); } @ParameterizedTest @MethodSource("providerMethod") void test2(String argument, TestInfo testInfo) { performTest(argument, testInfo); } private void performTest(String argument, TestInfo testInfo) { var testMethod = testInfo.getTestMethod().orElseThrow().getName(); testMethods.add(testMethod); lifecycleEvents.add(testMethod + ":" + testInfo.getDisplayName()); fail(argument); } static Stream providerMethod() { lifecycleEvents.add("providerMethod"); return Stream.of("foo", "bar"); } } private static class TwoSingleStringArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { return Stream.of(arguments("foo"), arguments("bar")); } } private static class TwoUnusedStringArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { return Stream.of(arguments("foo", "unused1"), arguments("bar", "unused2")); } } private static class StringLengthConverter implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return String.valueOf(source).length(); } } private static class StringAggregator implements ArgumentsAggregator { @Override public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException { return accessor.getString(0) + accessor.getString(1); } } private static class ErroneousConverter implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { throw new ArgumentConversionException("something went horribly wrong"); } } private static class AutoCloseableArgumentProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { return Stream.of(arguments(new AutoCloseableArgument())); } } static class AutoCloseableArgument implements AutoCloseable { static boolean isClosed = false; @Override public void close() { isClosed = true; } } static class Book { private final String title; private Book(String title) { this.title = title; } static Book factory(String title) { return new Book(title); } } } ParameterizedTestMethodContextTests.java000066400000000000000000000050761455764576500366560ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Method; import java.util.Arrays; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.params.aggregator.AggregatorIntegrationTests.CsvToPerson; import org.junit.jupiter.params.aggregator.AggregatorIntegrationTests.Person; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.provider.ValueSource; /** * Unit tests for {@link ParameterizedTestMethodContext}. * * @since 5.2 */ class ParameterizedTestMethodContextTests { @ParameterizedTest @ValueSource(strings = { "onePrimitive", "twoPrimitives", "twoAggregators", "twoAggregatorsWithTestInfoAtTheEnd", "mixedMode" }) void validSignatures(String name) { assertTrue(new ParameterizedTestMethodContext(method(name)).hasPotentiallyValidSignature()); } @ParameterizedTest @ValueSource(strings = { "twoAggregatorsWithPrimitiveInTheMiddle", "twoAggregatorsWithTestInfoInTheMiddle" }) void invalidSignatures(String name) { assertFalse(new ParameterizedTestMethodContext(method(name)).hasPotentiallyValidSignature()); } private Method method(String name) { return Arrays.stream(getClass().getDeclaredMethods()) // .filter(m -> m.getName().equals(name)) // .findFirst() // .orElseThrow(); } // --- VALID --------------------------------------------------------------- void onePrimitive(int num) { } void twoPrimitives(int num1, int num2) { } void twoAggregators(@CsvToPerson Person person, ArgumentsAccessor arguments) { } void twoAggregatorsWithTestInfoAtTheEnd(@CsvToPerson Person person1, @CsvToPerson Person person2, TestInfo testInfo) { } void mixedMode(int num1, int num2, ArgumentsAccessor arguments1, ArgumentsAccessor arguments2, @CsvToPerson Person person1, @CsvToPerson Person person2, TestInfo testInfo1, TestInfo testInfo2) { } // --- INVALID ------------------------------------------------------------- void twoAggregatorsWithPrimitiveInTheMiddle(@CsvToPerson Person person1, int num, @CsvToPerson Person person2) { } void twoAggregatorsWithTestInfoInTheMiddle(@CsvToPerson Person person1, TestInfo testInfo, @CsvToPerson Person person2) { } } ParameterizedTestNameFormatterTests.java000066400000000000000000000233531455764576500366330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.ParameterizedTest.ARGUMENTS_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.ARGUMENTS_WITH_NAMES_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.DISPLAY_NAME_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedTest.INDEX_PLACEHOLDER; import static org.mockito.Mockito.mock; import java.lang.reflect.Method; import java.math.BigDecimal; import java.sql.Date; import java.time.LocalDate; import java.time.LocalTime; import java.time.ZoneId; import java.util.Arrays; import java.util.Locale; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.aggregator.AggregateWith; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.aggregator.ArgumentsAggregator; import org.junit.jupiter.params.provider.CsvSource; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ class ParameterizedTestNameFormatterTests { private final Locale originalLocale = Locale.getDefault(); @AfterEach void restoreLocale() { Locale.setDefault(originalLocale); } @Test void formatsDisplayName() { var formatter = formatter(DISPLAY_NAME_PLACEHOLDER, "enigma"); assertEquals("enigma", formatter.format(1)); assertEquals("enigma", formatter.format(2)); } @Test void formatsDisplayNameContainingApostrophe() { String displayName = "display'Zero"; var formatter = formatter(DISPLAY_NAME_PLACEHOLDER, "display'Zero"); assertEquals(displayName, formatter.format(1)); assertEquals(displayName, formatter.format(2)); } @Test void formatsDisplayNameContainingFormatElements() { String displayName = "{enigma} {0} '{1}'"; var formatter = formatter(DISPLAY_NAME_PLACEHOLDER, displayName); assertEquals(displayName, formatter.format(1)); assertEquals(displayName, formatter.format(2)); } @Test void formatsInvocationIndex() { var formatter = formatter(INDEX_PLACEHOLDER, "enigma"); assertEquals("1", formatter.format(1)); assertEquals("2", formatter.format(2)); } @Test void formatsIndividualArguments() { var formatter = formatter("{0} -> {1}", "enigma"); assertEquals("foo -> 42", formatter.format(1, "foo", 42)); } @Test void formatsCompleteArgumentsList() { var formatter = formatter(ARGUMENTS_PLACEHOLDER, "enigma"); // @formatter:off assertEquals("42, 99, enigma, null, [1, 2, 3], [foo, bar], [[2, 4], [3, 9]]", formatter.format(1, 42, 99, "enigma", null, new int[] { 1, 2, 3 }, new String[] { "foo", "bar" }, new Integer[][] { { 2, 4 }, { 3, 9 } } )); // @formatter:on } @Test void formatsCompleteArgumentsListWithNames() { var testMethod = ParameterizedTestCases.getMethod("parameterizedTest", int.class, String.class, Object[].class); var formatter = formatter(ARGUMENTS_WITH_NAMES_PLACEHOLDER, "enigma", testMethod); var formattedName = formatter.format(1, 42, "enigma", new Object[] { "foo", 1 }); assertEquals("someNumber=42, someString=enigma, someArray=[foo, 1]", formattedName); } @Test void formatsCompleteArgumentsListWithoutNamesForAggregators() { var testMethod = ParameterizedTestCases.getMethod("parameterizedTestWithAggregator", int.class, String.class); var formatter = formatter(ARGUMENTS_WITH_NAMES_PLACEHOLDER, "enigma", testMethod); var formattedName = formatter.format(1, 42, "foo", "bar"); assertEquals("someNumber=42, foo, bar", formattedName); } @Test void formatsCompleteArgumentsListWithArrays() { var formatter = formatter(ARGUMENTS_PLACEHOLDER, "enigma"); // Explicit test for https://github.com/junit-team/junit5/issues/814 assertEquals("[foo, bar]", formatter.format(1, (Object) new String[] { "foo", "bar" })); assertEquals("[foo, bar], 42, true", formatter.format(1, new String[] { "foo", "bar" }, 42, true)); } @Test void formatsEverythingUsingCustomPattern() { var pattern = DISPLAY_NAME_PLACEHOLDER + " " + INDEX_PLACEHOLDER + " :: " + ARGUMENTS_PLACEHOLDER + " :: {1}"; var formatter = formatter(pattern, "enigma"); assertEquals("enigma 1 :: foo, bar :: bar", formatter.format(1, "foo", "bar")); assertEquals("enigma 2 :: foo, 42 :: 42", formatter.format(2, "foo", 42)); } @Test void formatDoesNotAlterArgumentsArray() { var formatter = formatter(ARGUMENTS_PLACEHOLDER, "enigma"); Object[] actual = { 1, "two", Byte.valueOf("-128"), new Integer[][] { { 2, 4 }, { 3, 9 } } }; var expected = Arrays.copyOf(actual, actual.length); assertEquals("1, two, -128, [[2, 4], [3, 9]]", formatter.format(1, actual)); assertArrayEquals(expected, actual); } @Test void formatDoesNotRaiseAnArrayStoreException() { var formatter = formatter("{0} -> {1}", "enigma"); Object[] arguments = new Number[] { 1, 2 }; assertEquals("1 -> 2", formatter.format(1, arguments)); } @Test void throwsReadableExceptionForInvalidPattern() { var formatter = formatter("{index", "enigma"); var exception = assertThrows(JUnitException.class, () -> formatter.format(1)); assertNotNull(exception.getCause()); assertEquals(IllegalArgumentException.class, exception.getCause().getClass()); } @Test void formattingDoesNotFailIfArgumentToStringImplementationReturnsNull() { var formatter = formatter(ARGUMENTS_PLACEHOLDER, "enigma"); var formattedName = formatter.format(1, new ToStringReturnsNull(), "foo"); assertThat(formattedName).isEqualTo("null, foo"); } @Test void formattingDoesNotFailIfArgumentToStringImplementationThrowsAnException() { var formatter = formatter(ARGUMENTS_PLACEHOLDER, "enigma"); var formattedName = formatter.format(1, new ToStringThrowsException(), "foo"); assertThat(formattedName).startsWith(ToStringThrowsException.class.getName() + "@"); assertThat(formattedName).endsWith("foo"); } @ParameterizedTest(name = "{0}") @CsvSource(delimiter = '|', value = { "US | 42.23 is positive on 2019 Jan 13 at 12:34:56", "DE | 42,23 is positive on 13.01.2019 at 12:34:56" }) void customFormattingExpressionsAreSupported(Locale locale, String expectedValue) { var pattern = "[{index}] {1,number,#.##} is {1,choice,0... parameterTypes) { return ReflectionUtils.findMethod(ParameterizedTestCases.class, methodName, parameterTypes).orElseThrow(); } @SuppressWarnings("unused") void parameterizedTest(int someNumber, String someString, Object[] someArray) { } @SuppressWarnings("unused") void parameterizedTestWithAggregator(int someNumber, @AggregateWith(CustomAggregator.class) String someAggregatedString) { } private static class CustomAggregator implements ArgumentsAggregator { @Override public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) { return accessor.get(0); } } } } ParameterizedTestSuite.java000066400000000000000000000021761455764576500341350ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; /** * Test suite for JUnit Jupiter parameterized test support. * *

Logging Configuration

* *

In order for our log4j2 configuration to be used in an IDE, you must * set the following system property before running any tests — for * example, in Run Configurations in Eclipse. * *

 * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
 * 
* * @since 5.0 */ @Suite @SelectPackages("org.junit.jupiter.params") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") class ParameterizedTestSuite { } junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/aggregator/000077500000000000000000000000001455764576500310175ustar00rootroot00000000000000AggregatorIntegrationTests.java000066400000000000000000000335541455764576500371260ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static java.util.stream.Collectors.toMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ArgumentConversionException; import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; /** * Integration tests for {@link ArgumentsAccessor}, {@link AggregateWith}, * and {@link ArgumentsAggregator}. * * @since 5.2 */ public class AggregatorIntegrationTests { @ParameterizedTest @CsvSource({ // "Jane, Doe, 1980-04-16, F, red", // "Jack, Smith, 2000-11-22, M, blue" // }) void personAggregator(@AggregateWith(PersonAggregator.class) Person person) { testPersonAggregator(person); } @ParameterizedTest @CsvSource({ // "Jane, Doe, 1980-04-16, F, red", // "Jack, Smith, 2000-11-22, M, blue" // }) void personAggregatorRegisteredViaCustomAnnotation(@CsvToPerson Person person) { testPersonAggregator(person); } @ParameterizedTest @CsvSource({ // "42 Peachtree Street, Atlanta, 30318", // "99 Peachtree Road, Atlanta, 30318"// }) void addressAggregator(@CsvToAddress Address address) { testAddressAggregator(address); } @ParameterizedTest @CsvSource({ // "Jane, Doe, 1980-04-16, F, 42 Peachtree Street, Atlanta, 30318, red", // "Jack, Smith, 2000-11-22, M, 99 Peachtree Road, Atlanta, 30318, blue"// }) void personAggregatorAndAddressAggregator(@CsvToPerson Person person, @CsvToAddress @StartIndex(4) Address address) { testPersonAggregator(person); testAddressAggregator(address); } @ParameterizedTest(name = "Mixed Mode #1: {arguments}") @CsvSource({ // "gh-11111111, Jane, Doe, 1980-04-16, F, 42 Peachtree Street, Atlanta, 30318, red", // "gh-22222222, Jack, Smith, 2000-11-22, M, 99 Peachtree Road, Atlanta, 30318, blue"// }) void mixedMode(String issueNumber, @CsvToPerson @StartIndex(1) Person person, @CsvToAddress @StartIndex(5) Address address, TestInfo testInfo) { assertThat(issueNumber).startsWith("gh-"); testPersonAggregator(person); testAddressAggregator(address); assertThat(testInfo.getDisplayName()).startsWith("Mixed Mode #1"); } @ParameterizedTest @CsvSource({ "cat, bird, mouse", "mouse, cat, bird", "mouse, bird, cat" }) void mapAggregator(@AggregateWith(MapAggregator.class) Map map) { assertThat(map).containsOnly(entry("cat", 3), entry("bird", 4), entry("mouse", 5)); } @ParameterizedTest @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void argumentsAccessor(ArgumentsAccessor arguments) { assertEquals(55, IntStream.range(0, arguments.size()).map(arguments::getInteger).sum()); } @ParameterizedTest(name = "2 ArgumentsAccessors: {arguments}") @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void argumentsAccessors(ArgumentsAccessor arguments1, ArgumentsAccessor arguments2) { assertArrayEquals(arguments1.toArray(), arguments2.toArray()); } @ParameterizedTest(name = "ArgumentsAccessor and TestInfo: {arguments}") @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void argumentsAccessorAndTestInfo(ArgumentsAccessor arguments, TestInfo testInfo) { assertEquals(55, IntStream.range(0, arguments.size()).map(arguments::getInteger).sum()); assertThat(testInfo.getDisplayName()).startsWith("ArgumentsAccessor and TestInfo"); } @ParameterizedTest(name = "Indexed Arguments and ArgumentsAccessor: {arguments}") @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void indexedArgumentsAndArgumentsAccessor(int num1, int num2, ArgumentsAccessor arguments) { assertEquals(1, num1); assertEquals(2, num2); assertEquals(55, IntStream.range(0, arguments.size()).map(arguments::getInteger).sum()); } @ParameterizedTest(name = "Indexed Arguments, ArgumentsAccessor, and TestInfo: {arguments}") @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void indexedArgumentsArgumentsAccessorAndTestInfo(int num1, int num2, ArgumentsAccessor arguments, TestInfo testInfo) { assertEquals(1, num1); assertEquals(2, num2); assertEquals(55, IntStream.range(0, arguments.size()).map(arguments::getInteger).sum()); assertThat(testInfo.getDisplayName()).startsWith("Indexed Arguments, ArgumentsAccessor, and TestInfo"); } @ParameterizedTest(name = "Indexed Arguments, 2 ArgumentsAccessors, and TestInfo: {arguments}") @CsvSource({ "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" }) void indexedArgumentsArgumentsAccessorsAndTestInfo(int num1, int num2, ArgumentsAccessor arguments1, ArgumentsAccessor arguments2, TestInfo testInfo) { assertEquals(1, num1); assertEquals(2, num2); assertArrayEquals(arguments1.toArray(), arguments2.toArray()); assertEquals(55, IntStream.range(0, arguments1.size()).map(arguments1::getInteger).sum()); assertThat(testInfo.getDisplayName()).startsWith("Indexed Arguments, 2 ArgumentsAccessors, and TestInfo"); } @ParameterizedTest @CsvSource({ "foo, bar" }) void nullAggregator(@AggregateWith(NullAggregator.class) Person person) { assertNull(person); } @Test void reportsExceptionForErroneousAggregator() { var results = execute( selectMethod(ErroneousTestCases.class, "testWithErroneousAggregator", Object.class.getName())); results.testEvents().assertThatEvents()// .haveExactly(1, event(test(), finishedWithFailure(instanceOf(ParameterResolutionException.class), // message("Error aggregating arguments for parameter at index 0: something went horribly wrong")))); } @ParameterizedTest @CsvSource({ // "first", // "second" // }) void argumentsAccessorInvocationIndex(ArgumentsAccessor arguments) { if ("first".equals(arguments.getString(0))) { assertEquals(1, arguments.getInvocationIndex()); } if ("second".equals(arguments.getString(0))) { assertEquals(2, arguments.getInvocationIndex()); } } private void testPersonAggregator(Person person) { if (person.firstName.equals("Jane")) { assertEquals("Jane Doe", person.getFullName()); assertEquals(1980, person.dateOfBirth.getYear()); assertEquals(Gender.F, person.gender); } if (person.firstName.equals("Jack")) { assertEquals("Jack Smith", person.getFullName()); assertEquals(2000, person.dateOfBirth.getYear()); assertEquals(Gender.M, person.gender); } } private void testAddressAggregator(Address address) { assertThat(address.street).contains("Peachtree"); assertEquals("Atlanta", address.city); assertEquals(30318, address.zipCode); } private EngineExecutionResults execute(DiscoverySelector... selectors) { return EngineTestKit.execute("junit-jupiter", request().selectors(selectors).build()); } // ------------------------------------------------------------------------- public static class Person { final String firstName; final String lastName; final Gender gender; final LocalDate dateOfBirth; Person(String firstName, String lastName, LocalDate dateOfBirth, Gender gender) { this.firstName = firstName; this.lastName = lastName; this.gender = gender; this.dateOfBirth = dateOfBirth; } String getFullName() { return this.firstName + " " + this.lastName; } } enum Gender { F, M } static class Address { final String street; final String city; final int zipCode; Address(String street, String city, int zipCode) { this.street = street; this.city = city; this.zipCode = zipCode; } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @interface StartIndex { int value(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @AggregateWith(PersonAggregator.class) public @interface CsvToPerson { } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @AggregateWith(AddressAggregator.class) @interface CsvToAddress { } static class PersonAggregator implements ArgumentsAggregator { @Override public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) { int startIndex = context.findAnnotation(StartIndex.class).map(StartIndex::value).orElse(0); // @formatter:off return new Person( arguments.getString(startIndex + 0), arguments.getString(startIndex + 1), arguments.get(startIndex + 2, LocalDate.class), arguments.get(startIndex + 3, Gender.class) ); // @formatter:on } } static class AddressAggregator implements ArgumentsAggregator { @Override public Address aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) { int startIndex = context.findAnnotation(StartIndex.class).map(StartIndex::value).orElse(0); // @formatter:off return new Address( arguments.getString(startIndex + 0), arguments.getString(startIndex + 1), arguments.getInteger(startIndex + 2) ); // @formatter:on } } /** * Maps from String to length of String. */ static class MapAggregator implements ArgumentsAggregator { @Override public Map aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) { // @formatter:off return IntStream.range(0, arguments.size()) .mapToObj(arguments::getString) .collect(toMap(s -> s, String::length)); // @formatter:on } } static class NullAggregator implements ArgumentsAggregator { @Override public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) { Preconditions.condition(!context.getParameter().getType().isPrimitive(), () -> "only supports reference types"); return null; } } static class ErroneousAggregator implements ArgumentsAggregator { @Override public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException { throw new ArgumentsAggregationException("something went horribly wrong"); } } static class ErroneousTestCases { @ParameterizedTest @ValueSource(ints = 42) void testWithErroneousAggregator(@AggregateWith(ErroneousAggregator.class) Object ignored) { fail("this should never be called"); } } @Test @ResourceLock("InstanceCountingConverter.instanceCount") void aggregatorIsInstantiatedOnlyOnce() { InstanceCountingAggregator.instanceCount = 0; CountingTestCase.output.clear(); execute(selectMethod(CountingTestCase.class, "testWithCountingConverterAggregator", int.class.getName() + "," + Object.class.getName())); assertThat(InstanceCountingAggregator.instanceCount).isEqualTo(1); assertThat(CountingTestCase.output)// .containsExactly("noisy test(1, enigma)", "noisy test(2, enigma)", "noisy test(3, enigma)"); } @Test @ResourceLock("InstanceCountingConverter.instanceCount") void converterIsInstantiatedOnlyOnce() { InstanceCountingConverter.instanceCount = 0; CountingTestCase.output.clear(); execute(selectMethod(CountingTestCase.class, "testWithCountingConverterAggregator", int.class.getName() + "," + Object.class.getName())); assertThat(InstanceCountingConverter.instanceCount).isEqualTo(1); assertThat(CountingTestCase.output)// .containsExactly("noisy test(1, enigma)", "noisy test(2, enigma)", "noisy test(3, enigma)"); } static class InstanceCountingConverter implements ArgumentConverter { static int instanceCount; InstanceCountingConverter() { instanceCount++; } @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return source; } } static class InstanceCountingAggregator implements ArgumentsAggregator { static int instanceCount; InstanceCountingAggregator() { instanceCount++; } @Override public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException { return "enigma"; } } static class CountingTestCase { static final List output = new ArrayList<>(); @ParameterizedTest @ValueSource(ints = { 1, 2, 3 }) void testWithCountingConverterAggregator(@ConvertWith(InstanceCountingConverter.class) int i, @AggregateWith(InstanceCountingAggregator.class) Object o) { output.add("noisy test(" + i + ", " + o + ")"); } } } DefaultArgumentsAccessorTests.java000066400000000000000000000134711455764576500375710ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.Arrays; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link DefaultArgumentsAccessor}. * * @since 5.2 */ class DefaultArgumentsAccessorTests { @Test void argumentsMustNotBeNull() { assertThrows(PreconditionViolationException.class, () -> defaultArgumentsAccessor(1, (Object[]) null)); } @Test void indexMustNotBeNegative() { ArgumentsAccessor arguments = defaultArgumentsAccessor(1, 1, 2); Exception exception = assertThrows(PreconditionViolationException.class, () -> arguments.get(-1)); assertThat(exception.getMessage()).containsSubsequence("index must be", ">= 0"); } @Test void indexMustBeSmallerThanLength() { ArgumentsAccessor arguments = defaultArgumentsAccessor(1, 1, 2); Exception exception = assertThrows(PreconditionViolationException.class, () -> arguments.get(2)); assertThat(exception.getMessage()).containsSubsequence("index must be", "< 2"); } @Test void getNull() { assertNull(defaultArgumentsAccessor(1, new Object[] { null }).get(0)); } @Test void getWithNullCastToWrapperType() { assertNull(defaultArgumentsAccessor(1, (Object[]) new Integer[] { null }).get(0, Integer.class)); } @Test void get() { assertEquals(1, defaultArgumentsAccessor(1, 1).get(0)); } @Test void getWithCast() { assertEquals(Integer.valueOf(1), defaultArgumentsAccessor(1, 1).get(0, Integer.class)); assertEquals(Character.valueOf('A'), defaultArgumentsAccessor(1, 'A').get(0, Character.class)); } @Test void getWithCastToPrimitiveType() { Exception exception = assertThrows(ArgumentAccessException.class, () -> defaultArgumentsAccessor(1, 1).get(0, int.class)); assertThat(exception.getMessage()).isEqualTo( "Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [int]."); exception = assertThrows(ArgumentAccessException.class, () -> defaultArgumentsAccessor(1, new Object[] { null }).get(0, int.class)); assertThat(exception.getMessage()).isEqualTo( "Argument at index [0] with value [null] and type [null] could not be converted or cast to type [int]."); } @Test void getWithCastToIncompatibleType() { Exception exception = assertThrows(ArgumentAccessException.class, () -> defaultArgumentsAccessor(1, 1).get(0, Character.class)); assertThat(exception.getMessage()).isEqualTo( "Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [java.lang.Character]."); } @Test void getCharacter() { assertEquals(Character.valueOf('A'), defaultArgumentsAccessor(1, 'A', 'B').getCharacter(0)); } @Test void getBoolean() { assertEquals(Boolean.TRUE, defaultArgumentsAccessor(1, true, false).getBoolean(0)); } @Test void getByte() { assertEquals(Byte.valueOf((byte) 42), defaultArgumentsAccessor(1, (byte) 42).getByte(0)); } @Test void getShort() { assertEquals(Short.valueOf((short) 42), defaultArgumentsAccessor(1, (short) 42).getShort(0)); } @Test void getInteger() { assertEquals(Integer.valueOf(42), defaultArgumentsAccessor(1, 42).getInteger(0)); } @Test void getLong() { assertEquals(Long.valueOf(42L), defaultArgumentsAccessor(1, 42L).getLong(0)); } @Test void getFloat() { assertEquals(Float.valueOf(42.0f), defaultArgumentsAccessor(1, 42.0f).getFloat(0)); } @Test void getDouble() { assertEquals(Double.valueOf(42.0), defaultArgumentsAccessor(1, 42.0).getDouble(0)); } @Test void getString() { assertEquals("foo", defaultArgumentsAccessor(1, "foo", "bar").getString(0)); } @Test void toArray() { var arguments = defaultArgumentsAccessor(1, "foo", "bar"); var copy = arguments.toArray(); assertArrayEquals(new String[] { "foo", "bar" }, copy); // Modify local copy: copy[0] = "Boom!"; assertEquals("foo", arguments.toArray()[0]); } @Test void toList() { var arguments = defaultArgumentsAccessor(1, "foo", "bar"); var copy = arguments.toList(); assertIterableEquals(Arrays.asList("foo", "bar"), copy); // Modify local copy: assertThrows(UnsupportedOperationException.class, () -> copy.set(0, "Boom!")); } @Test void size() { assertEquals(0, defaultArgumentsAccessor(1).size()); assertEquals(1, defaultArgumentsAccessor(1, 42).size()); assertEquals(5, defaultArgumentsAccessor(1, 'a', 'b', 'c', 'd', 'e').size()); } private static DefaultArgumentsAccessor defaultArgumentsAccessor(int invocationIndex, Object... arguments) { return new DefaultArgumentsAccessor(parameterContext(), invocationIndex, arguments); } private static ParameterContext parameterContext() { Method declaringExecutable = ReflectionUtils.findMethod(DefaultArgumentsAccessorTests.class, "foo").get(); ParameterContext parameterContext = mock(); when(parameterContext.getDeclaringExecutable()).thenReturn(declaringExecutable); return parameterContext; } @SuppressWarnings("unused") private static void foo() { } } junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/000077500000000000000000000000001455764576500307045ustar00rootroot00000000000000DefaultArgumentConverterTests.java000066400000000000000000000352661455764576500375060ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; import java.lang.Thread.State; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.Period; import java.time.Year; import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Currency; import java.util.Locale; import java.util.UUID; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link DefaultArgumentConverter}. * * @since 5.0 */ class DefaultArgumentConverterTests { @Test void isAwareOfNull() { assertConverts(null, Object.class, null); assertConverts(null, String.class, null); assertConverts(null, Boolean.class, null); } @Test void isAwareOfWrapperTypesForPrimitiveTypes() { assertConverts(true, boolean.class, true); assertConverts(false, boolean.class, false); assertConverts((byte) 1, byte.class, (byte) 1); assertConverts('o', char.class, 'o'); assertConverts((short) 1, short.class, (short) 1); assertConverts(1, int.class, 1); assertConverts(1L, long.class, 1L); assertConverts(1.0f, float.class, 1.0f); assertConverts(1.0d, double.class, 1.0d); } @Test void isAwareOfWideningConversions() { assertConverts((byte) 1, short.class, (byte) 1); assertConverts((short) 1, int.class, (short) 1); assertConverts((char) 1, int.class, (char) 1); assertConverts((byte) 1, long.class, (byte) 1); assertConverts(1, long.class, 1); assertConverts((char) 1, float.class, (char) 1); assertConverts(1, float.class, 1); assertConverts(1L, double.class, 1L); assertConverts(1.0f, double.class, 1.0f); } @Test void convertsStringsToPrimitiveTypes() { assertConverts("true", boolean.class, true); assertConverts("false", boolean.class, false); assertConverts("o", char.class, 'o'); assertConverts("1", byte.class, (byte) 1); assertConverts("1_0", byte.class, (byte) 10); assertConverts("1", short.class, (short) 1); assertConverts("1_2", short.class, (short) 12); assertConverts("42", int.class, 42); assertConverts("700_050_000", int.class, 700_050_000); assertConverts("42", long.class, 42L); assertConverts("4_2", long.class, 42L); assertConverts("42.23", float.class, 42.23f); assertConverts("42.2_3", float.class, 42.23f); assertConverts("42.23", double.class, 42.23); assertConverts("42.2_3", double.class, 42.23); } @Test void convertsStringsToPrimitiveWrapperTypes() { assertConverts("true", Boolean.class, true); assertConverts("false", Boolean.class, false); assertConverts("o", Character.class, 'o'); assertConverts("1", Byte.class, (byte) 1); assertConverts("1_0", Byte.class, (byte) 10); assertConverts("1", Short.class, (short) 1); assertConverts("1_2", Short.class, (short) 12); assertConverts("42", Integer.class, 42); assertConverts("700_050_000", Integer.class, 700_050_000); assertConverts("42", Long.class, 42L); assertConverts("4_2", Long.class, 42L); assertConverts("42.23", Float.class, 42.23f); assertConverts("42.2_3", Float.class, 42.23f); assertConverts("42.23", Double.class, 42.23); assertConverts("42.2_3", Double.class, 42.23); } @ParameterizedTest(name = "[{index}] {0}") @ValueSource(classes = { char.class, boolean.class, short.class, byte.class, int.class, long.class, float.class, double.class }) void throwsExceptionForNullToPrimitiveTypeConversion(Class type) { assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert(null, type)) // .withMessage("Cannot convert null to primitive value of type " + type.getCanonicalName()); } @ParameterizedTest(name = "[{index}] {0}") @ValueSource(classes = { Boolean.class, Character.class, Short.class, Byte.class, Integer.class, Long.class, Float.class, Double.class }) void throwsExceptionWhenConvertingTheWordNullToPrimitiveWrapperType(Class type) { assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("null", type)) // .withMessage("Failed to convert String \"null\" to type " + type.getCanonicalName()); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("NULL", type)) // .withMessage("Failed to convert String \"NULL\" to type " + type.getCanonicalName()); } @Test void throwsExceptionOnInvalidStringForPrimitiveTypes() { assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("ab", char.class)) // .withMessage("Failed to convert String \"ab\" to type char") // .havingCause() // .withMessage("String must have length of 1: ab"); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("tru", boolean.class)) // .withMessage("Failed to convert String \"tru\" to type boolean") // .havingCause() // .withMessage("String must be 'true' or 'false' (ignoring case): tru"); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("null", boolean.class)) // .withMessage("Failed to convert String \"null\" to type boolean") // .havingCause() // .withMessage("String must be 'true' or 'false' (ignoring case): null"); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("NULL", boolean.class)) // .withMessage("Failed to convert String \"NULL\" to type boolean") // .havingCause() // .withMessage("String must be 'true' or 'false' (ignoring case): NULL"); } @Test void throwsExceptionWhenImplicitConverstionIsUnsupported() { assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert("foo", Enigma.class)) // .withMessage("No built-in converter for source type java.lang.String and target type %s", Enigma.class.getName()); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert(new Enigma(), int[].class)) // .withMessage("No built-in converter for source type %s and target type int[]", Enigma.class.getName()); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert(new long[] {}, int[].class)) // .withMessage("No built-in converter for source type long[] and target type int[]"); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert(new String[] {}, boolean.class)) // .withMessage("No built-in converter for source type java.lang.String[] and target type boolean"); assertThatExceptionOfType(ArgumentConversionException.class) // .isThrownBy(() -> convert(Class.class, int[].class)) // .withMessage("No built-in converter for source type java.lang.Class and target type int[]"); } /** * @since 5.4 */ @Test @SuppressWarnings("OctalInteger") // We test parsing octal integers here as well as hex. void convertsEncodedStringsToIntegralTypes() { assertConverts("0x1f", byte.class, (byte) 0x1F); assertConverts("-0x1F", byte.class, (byte) -0x1F); assertConverts("010", byte.class, (byte) 010); assertConverts("0x1f00", short.class, (short) 0x1F00); assertConverts("-0x1F00", short.class, (short) -0x1F00); assertConverts("01000", short.class, (short) 01000); assertConverts("0x1f000000", int.class, 0x1F000000); assertConverts("-0x1F000000", int.class, -0x1F000000); assertConverts("010000000", int.class, 010000000); assertConverts("0x1f000000000", long.class, 0x1F000000000L); assertConverts("-0x1F000000000", long.class, -0x1F000000000L); assertConverts("0100000000000", long.class, 0100000000000L); } @Test void convertsStringsToEnumConstants() { assertConverts("DAYS", TimeUnit.class, TimeUnit.DAYS); } // --- java.io and java.nio ------------------------------------------------ @Test void convertsStringToCharset() { assertConverts("ISO-8859-1", Charset.class, StandardCharsets.ISO_8859_1); assertConverts("UTF-8", Charset.class, StandardCharsets.UTF_8); } @Test void convertsStringToFile() { assertConverts("file", File.class, new File("file")); assertConverts("/file", File.class, new File("/file")); assertConverts("/some/file", File.class, new File("/some/file")); } @Test void convertsStringToPath() { assertConverts("path", Path.class, Paths.get("path")); assertConverts("/path", Path.class, Paths.get("/path")); assertConverts("/some/path", Path.class, Paths.get("/some/path")); } // --- java.lang ----------------------------------------------------------- @Test void convertsStringToClass() { assertConverts("java.lang.Integer", Class.class, Integer.class); assertConverts("java.lang.Thread$State", Class.class, State.class); assertConverts("byte", Class.class, byte.class); assertConverts("char[]", Class.class, char[].class); assertConverts("java.lang.Long[][]", Class.class, Long[][].class); assertConverts("[[[I", Class.class, int[][][].class); assertConverts("[[Ljava.lang.String;", Class.class, String[][].class); } @Test void convertsStringToClassWithCustomTypeFromDifferentClassLoader() throws Exception { String customTypeName = Enigma.class.getName(); try (var testClassLoader = TestClassLoader.forClasses(Enigma.class)) { var customType = testClassLoader.loadClass(customTypeName); assertThat(customType.getClassLoader()).isSameAs(testClassLoader); var declaringExecutable = ReflectionUtils.findMethod(customType, "foo").get(); assertThat(declaringExecutable.getDeclaringClass().getClassLoader()).isSameAs(testClassLoader); var clazz = (Class) convert(customTypeName, Class.class, parameterContext(declaringExecutable)); assertThat(clazz).isNotEqualTo(Enigma.class); assertThat(clazz).isEqualTo(customType); assertThat(clazz.getClassLoader()).isSameAs(testClassLoader); } } // --- java.math ----------------------------------------------------------- @Test void convertsStringToBigDecimal() { assertConverts("123.456e789", BigDecimal.class, new BigDecimal("123.456e789")); } @Test void convertsStringToBigInteger() { assertConverts("1234567890123456789", BigInteger.class, new BigInteger("1234567890123456789")); } // --- java.net ------------------------------------------------------------ @Test void convertsStringToURI() { assertConverts("https://docs.oracle.com/en/java/javase/12/", URI.class, URI.create("https://docs.oracle.com/en/java/javase/12/")); } @Test void convertsStringToURL() throws Exception { assertConverts("https://junit.org/junit5", URL.class, URI.create("https://junit.org/junit5").toURL()); } // --- java.time ----------------------------------------------------------- @Test void convertsStringsToJavaTimeInstances() { assertConverts("PT1234.5678S", Duration.class, Duration.ofSeconds(1234, 567800000)); assertConverts("1970-01-01T00:00:00Z", Instant.class, Instant.ofEpochMilli(0)); assertConverts("2017-03-14", LocalDate.class, LocalDate.of(2017, 3, 14)); assertConverts("2017-03-14T12:34:56.789", LocalDateTime.class, LocalDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000)); assertConverts("12:34:56.789", LocalTime.class, LocalTime.of(12, 34, 56, 789_000_000)); assertConverts("--03-14", MonthDay.class, MonthDay.of(3, 14)); assertConverts("2017-03-14T12:34:56.789Z", OffsetDateTime.class, OffsetDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000, ZoneOffset.UTC)); assertConverts("12:34:56.789Z", OffsetTime.class, OffsetTime.of(12, 34, 56, 789_000_000, ZoneOffset.UTC)); assertConverts("P2M6D", Period.class, Period.of(0, 2, 6)); assertConverts("2017", Year.class, Year.of(2017)); assertConverts("2017-03", YearMonth.class, YearMonth.of(2017, 3)); assertConverts("2017-03-14T12:34:56.789Z", ZonedDateTime.class, ZonedDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000, ZoneOffset.UTC)); assertConverts("Europe/Berlin", ZoneId.class, ZoneId.of("Europe/Berlin")); assertConverts("+02:30", ZoneOffset.class, ZoneOffset.ofHoursMinutes(2, 30)); } // --- java.util ----------------------------------------------------------- @Test void convertsStringToCurrency() { assertConverts("JPY", Currency.class, Currency.getInstance("JPY")); } @Test void convertsStringToLocale() { assertConverts("en", Locale.class, Locale.ENGLISH); assertConverts("en_us", Locale.class, new Locale(Locale.US.toString())); } @Test void convertsStringToUUID() { var uuid = "d043e930-7b3b-48e3-bdbe-5a3ccfb833db"; assertConverts(uuid, UUID.class, UUID.fromString(uuid)); } // ------------------------------------------------------------------------- private void assertConverts(Object input, Class targetClass, Object expectedOutput) { var result = convert(input, targetClass); assertThat(result) // .describedAs(input + " --(" + targetClass.getName() + ")--> " + expectedOutput) // .isEqualTo(expectedOutput); } private Object convert(Object input, Class targetClass) { return convert(input, targetClass, parameterContext()); } private Object convert(Object input, Class targetClass, ParameterContext parameterContext) { return DefaultArgumentConverter.INSTANCE.convert(input, targetClass, parameterContext); } private static ParameterContext parameterContext() { Method declaringExecutable = ReflectionUtils.findMethod(DefaultArgumentConverterTests.class, "foo").get(); return parameterContext(declaringExecutable); } private static ParameterContext parameterContext(Method declaringExecutable) { ParameterContext parameterContext = mock(); when(parameterContext.getDeclaringExecutable()).thenReturn(declaringExecutable); return parameterContext; } @SuppressWarnings("unused") private static void foo() { } private static class Enigma { @SuppressWarnings("unused") void foo() { } } } FallbackStringToObjectConverterTests.java000066400000000000000000000145351455764576500407330ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.converter.FallbackStringToObjectConverter.IsFactoryConstructor; import org.junit.jupiter.params.converter.FallbackStringToObjectConverter.IsFactoryMethod; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link FallbackStringToObjectConverter}, {@link IsFactoryMethod}, * and {@link IsFactoryConstructor}. * * @since 5.1 */ class FallbackStringToObjectConverterTests { private static final IsFactoryMethod isBookFactoryMethod = new IsFactoryMethod(Book.class); private static final FallbackStringToObjectConverter converter = new FallbackStringToObjectConverter(); @Test void isNotFactoryMethodForWrongParameterType() { assertThat(isBookFactoryMethod).rejects(bookMethod("factory", Object.class)); } @Test void isNotFactoryMethodForPrivateMethod() { assertThat(isBookFactoryMethod).rejects(bookMethod("privateFactory")); } @Test void isNotFactoryMethodForNonStaticMethod() { assertThat(isBookFactoryMethod).rejects(bookMethod("nonStaticFactory")); } @Test void isFactoryMethodForValidMethods() { assertThat(isBookFactoryMethod).accepts(bookMethod("factory")); assertThat(new IsFactoryMethod(Newspaper.class)).accepts(newspaperMethod("from"), newspaperMethod("of")); assertThat(new IsFactoryMethod(Magazine.class)).accepts(magazineMethod("from"), magazineMethod("of")); } @Test void isNotFactoryConstructorForPrivateConstructor() { assertThat(new IsFactoryConstructor(Magazine.class)).rejects(constructor(Magazine.class)); } @Test void isFactoryConstructorForValidConstructors() { assertThat(new IsFactoryConstructor(Book.class)).accepts(constructor(Book.class)); assertThat(new IsFactoryConstructor(Journal.class)).accepts(constructor(Journal.class)); assertThat(new IsFactoryConstructor(Newspaper.class)).accepts(constructor(Newspaper.class)); } @Test void convertsStringToBookViaStaticFactoryMethod() throws Exception { assertConverts("enigma", Book.class, Book.factory("enigma")); } @Test void convertsStringToJournalViaFactoryConstructor() throws Exception { assertConverts("enigma", Journal.class, new Journal("enigma")); } @Test void convertsStringToNewspaperViaConstructorIgnoringMultipleFactoryMethods() throws Exception { assertConverts("enigma", Newspaper.class, new Newspaper("enigma")); } @Test @DisplayName("Cannot convert String to Diary because Diary has neither a static factory method nor a factory constructor") void cannotConvertStringToDiary() { assertThat(converter.canConvert(Diary.class)).isFalse(); } @Test @DisplayName("Cannot convert String to Magazine because Magazine has multiple static factory methods") void cannotConvertStringToMagazine() { assertThat(converter.canConvert(Magazine.class)).isFalse(); } // ------------------------------------------------------------------------- private static Constructor constructor(Class clazz) { return ReflectionUtils.findConstructors(clazz, ctr -> ctr.getParameterCount() == 1 && ctr.getParameterTypes()[0] == String.class).get(0); } private static Method bookMethod(String methodName) { return bookMethod(methodName, String.class); } private static Method bookMethod(String methodName, Class parameterType) { return findMethod(Book.class, methodName, parameterType).orElseThrow(); } private static Method newspaperMethod(String methodName) { return findMethod(Newspaper.class, methodName, String.class).orElseThrow(); } private static Method magazineMethod(String methodName) { return findMethod(Magazine.class, methodName, String.class).orElseThrow(); } private static void assertConverts(String input, Class targetType, Object expectedOutput) throws Exception { assertThat(converter.canConvert(targetType)).isTrue(); var result = converter.convert(input, targetType); assertThat(result) // .describedAs(input + " --(" + targetType.getName() + ")--> " + expectedOutput) // .isEqualTo(expectedOutput); } static class Book { private final String title; Book(String title) { this.title = title; } // static and non-private static Book factory(String title) { return new Book(title); } // wrong parameter type static Book factory(Object obj) { return new Book(String.valueOf(obj)); } @SuppressWarnings("unused") private static Book privateFactory(String title) { return new Book(title); } Book nonStaticFactory(String title) { return new Book(title); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Book)) { return false; } var that = (Book) obj; return Objects.equals(this.title, that.title); } } static class Journal { private final String title; Journal(String title) { this.title = title; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Journal)) { return false; } var that = (Journal) obj; return Objects.equals(this.title, that.title); } } static class Newspaper { private final String title; Newspaper(String title) { this.title = title; } static Newspaper from(String title) { return new Newspaper(title); } static Newspaper of(String title) { return new Newspaper(title); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Newspaper)) { return false; } var that = (Newspaper) obj; return Objects.equals(this.title, that.title); } } static class Magazine { private Magazine(String title) { } static Magazine from(String title) { return new Magazine(title); } static Magazine of(String title) { return new Magazine(title); } } static class Diary { } } JavaTimeArgumentConverterTests.java000066400000000000000000000074511455764576500376150ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static java.time.ZoneOffset.UTC; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.Year; import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoZonedDateTime; import org.junit.jupiter.api.Test; /** * @since 5.0 */ class JavaTimeArgumentConverterTests { @Test void convertsStringToChronoLocalDate() { assertThat(convert("01.02.2017", "dd.MM.yyyy", ChronoLocalDate.class)) // .isEqualTo(LocalDate.of(2017, 2, 1)); } @Test void convertsStringToChronoLocalDateTime() { assertThat(convert("01.02.2017 12:34:56.789", "dd.MM.yyyy HH:mm:ss.SSS", ChronoLocalDateTime.class)) // .isEqualTo(LocalDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000)); } @Test void convertsStringToChronoZonedDateTime() { assertThat(convert("01.02.2017 12:34:56.789 Z", "dd.MM.yyyy HH:mm:ss.SSS X", ChronoZonedDateTime.class)) // .isEqualTo(ZonedDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000, UTC)); } @Test void convertsStringToLocalDate() { assertThat(convert("01.02.2017", "dd.MM.yyyy", LocalDate.class)) // .isEqualTo(LocalDate.of(2017, 2, 1)); } @Test void convertsStringToLocalDateTime() { assertThat(convert("01.02.2017 12:34:56.789", "dd.MM.yyyy HH:mm:ss.SSS", LocalDateTime.class)) // .isEqualTo(LocalDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000)); } @Test void convertsStringToLocalTime() { assertThat(convert("12:34:56.789", "HH:mm:ss.SSS", LocalTime.class)) // .isEqualTo(LocalTime.of(12, 34, 56, 789_000_000)); } @Test void convertsStringToOffsetDateTime() { assertThat(convert("01.02.2017 12:34:56.789 +02", "dd.MM.yyyy HH:mm:ss.SSS X", OffsetDateTime.class)) // .isEqualTo(OffsetDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000, ZoneOffset.ofHours(2))); } @Test void convertsStringToOffsetTime() { assertThat(convert("12:34:56.789 -02", "HH:mm:ss.SSS X", OffsetTime.class)) // .isEqualTo(OffsetTime.of(12, 34, 56, 789_000_000, ZoneOffset.ofHours(-2))); } @Test void convertsStringToYear() { assertThat(convert("2017", "yyyy", Year.class)) // .isEqualTo(Year.of(2017)); } @Test void convertsStringToYearMonth() { assertThat(convert("03/2017", "MM/yyyy", YearMonth.class)) // .isEqualTo(YearMonth.of(2017, 3)); } @Test void convertsStringToZonedDateTime() { assertThat(convert("01.02.2017 12:34:56.789 Europe/Berlin", "dd.MM.yyyy HH:mm:ss.SSS VV", ZonedDateTime.class)) // .isEqualTo(ZonedDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000, ZoneId.of("Europe/Berlin"))); } @Test void throwsExceptionOnInvalidTargetType() { var exception = assertThrows(ArgumentConversionException.class, () -> convert("2017", "yyyy", Integer.class)); assertThat(exception).hasMessage("Cannot convert to java.lang.Integer: 2017"); } private Object convert(Object input, String pattern, Class targetClass) { var converter = new JavaTimeArgumentConverter(); var annotation = mock(JavaTimeConversionPattern.class); when(annotation.value()).thenReturn(pattern); return converter.convert(input, targetClass, annotation); } } TypedArgumentConverterTests.java000066400000000000000000000123211455764576500371720ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.converter; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertAll; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; /** * Tests for {@link TypedArgumentConverter}. * * @since 5.7 */ class TypedArgumentConverterTests { @Nested class UnitTests { private final StringLengthArgumentConverter converter = new StringLengthArgumentConverter(); /** * @since 5.8 */ @Test void preconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> new StringLengthArgumentConverter(null, Integer.class))// .withMessage("sourceType must not be null"); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> new StringLengthArgumentConverter(String.class, null))// .withMessage("targetType must not be null"); } @Test void convertsSourceToTarget() { assertAll(// () -> assertConverts("abcd", 4), // () -> assertConverts("", 0), // () -> assertConverts(null, 0)// ); } private void assertConverts(String input, int expected) { assertThat(this.converter.convert(input)).isEqualTo(expected); } @Test void sourceTypeMismatch() { Parameter parameter = findParameterOfMethod("stringToBoolean", Boolean.class); ParameterContext parameterContext = parameterContext(parameter); assertThatExceptionOfType(ArgumentConversionException.class)// .isThrownBy(() -> this.converter.convert(Boolean.TRUE, parameterContext))// .withMessage("StringLengthArgumentConverter cannot convert objects of type [java.lang.Boolean]. " + "Only source objects of type [java.lang.String] are supported."); } @Test void targetTypeMismatch() { Parameter parameter = findParameterOfMethod("stringToBoolean", Boolean.class); ParameterContext parameterContext = parameterContext(parameter); assertThatExceptionOfType(ArgumentConversionException.class)// .isThrownBy(() -> this.converter.convert("enigma", parameterContext))// .withMessage("StringLengthArgumentConverter cannot convert to type [java.lang.Boolean]. " + "Only target type [java.lang.Integer] is supported."); } private ParameterContext parameterContext(Parameter parameter) { ParameterContext parameterContext = mock(); when(parameterContext.getParameter()).thenReturn(parameter); return parameterContext; } private Parameter findParameterOfMethod(String methodName, Class... parameterTypes) { Method method = ReflectionUtils.findMethod(getClass(), methodName, parameterTypes).get(); return method.getParameters()[0]; } void stringToBoolean(Boolean b) { } } /** * @since 5.8 */ @Nested class IntegrationTests { @ParameterizedTest @NullSource void nullStringToInteger(@StringLength Integer length) { assertThat(length).isEqualTo(0); } @ParameterizedTest @NullSource void nullStringToPrimitiveInt(@StringLength int length) { assertThat(length).isEqualTo(0); } @ParameterizedTest @NullSource void nullStringToPrimitiveLong(@StringLength long length) { assertThat(length).isEqualTo(0); } @ParameterizedTest @ValueSource(strings = "enigma") void stringToInteger(@StringLength Integer length) { assertThat(length).isEqualTo(6); } @ParameterizedTest @ValueSource(strings = "enigma") void stringToPrimitiveInt(@StringLength int length) { assertThat(length).isEqualTo(6); } @ParameterizedTest @ValueSource(strings = "enigma") void stringToPrimitiveLong(@StringLength long length) { assertThat(length).isEqualTo(6); } } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @ConvertWith(StringLengthArgumentConverter.class) private @interface StringLength { } private static class StringLengthArgumentConverter extends TypedArgumentConverter { StringLengthArgumentConverter() { this(String.class, Integer.class); } StringLengthArgumentConverter(Class sourceType, Class targetType) { super(sourceType, targetType); } @Override protected Integer convert(String source) throws ArgumentConversionException { return (source != null ? source.length() : 0); } } } junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/000077500000000000000000000000001455764576500305275ustar00rootroot00000000000000AnnotationBasedArgumentsProviderTests.java000066400000000000000000000041271455764576500410140ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.params.provider.MockCsvAnnotationBuilder.csvSource; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atMostOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; @DisplayName("AnnotationBasedArgumentsProvider") class AnnotationBasedArgumentsProviderTests { private final AnnotationBasedArgumentsProvider annotationBasedArgumentsProvider = new AnnotationBasedArgumentsProvider<>() { @Override protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { return Stream.empty(); } }; @Test @DisplayName("should throw exception when null annotation is provided to accept method") void shouldThrowExceptionWhenNullAnnotationIsProvidedToAccept() { assertThatThrownBy(() -> annotationBasedArgumentsProvider.accept(null)) // .hasMessage("annotation must not be null"); } @Test @DisplayName("should invoke the provideArguments template method with the accepted annotation") void shouldInvokeTemplateMethodWithTheAnnotationProvidedToAccept() { var spiedProvider = spy(annotationBasedArgumentsProvider); var extensionContext = mock(ExtensionContext.class); var annotation = csvSource("0", "1", "2"); annotationBasedArgumentsProvider.accept(annotation); annotationBasedArgumentsProvider.provideArguments(extensionContext); verify(spiedProvider, atMostOnce()).provideArguments(eq(extensionContext), eq(annotation)); } } ArgumentsTests.java000066400000000000000000000025571455764576500343140ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.jupiter.params.provider.Arguments.of; import org.junit.jupiter.api.Test; /** * Unit tests for {@link Arguments}. * * @since 5.0 */ class ArgumentsTests { @Test void ofSupportsVarargs() { var arguments = of(1, "2", 3.0); assertArrayEquals(new Object[] { 1, "2", 3.0 }, arguments.get()); } @Test void argumentsSupportsVarargs() { var arguments = arguments(1, "2", 3.0); assertArrayEquals(new Object[] { 1, "2", 3.0 }, arguments.get()); } @Test void ofReturnsSameArrayUsedForCreating() { Object[] input = { 1, "2", 3.0 }; var arguments = of(input); assertThat(arguments.get()).isSameAs(input); } @Test void argumentsReturnsSameArrayUsedForCreating() { Object[] input = { 1, "2", 3.0 }; var arguments = arguments(input); assertThat(arguments.get()).isSameAs(input); } } CsvArgumentsProviderTests.java000066400000000000000000000265151455764576500365030ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.params.provider.MockCsvAnnotationBuilder.csvSource; import static org.mockito.Mockito.mock; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; /** * @since 5.0 */ class CsvArgumentsProviderTests { @Test void throwsExceptionForInvalidCsv() { var annotation = csvSource("foo", "bar", ""); assertThatExceptionOfType(JUnitException.class)// .isThrownBy(() -> provideArguments(annotation).toArray())// .withMessage("Record at index 3 contains invalid CSV: \"\""); } @Test void throwsExceptionIfNeitherValueNorTextBlockIsDeclared() { var annotation = csvSource().build(); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessage("@CsvSource must be declared with either `value` or `textBlock` but not both"); } @Test void throwsExceptionIfValueAndTextBlockAreDeclared() { var annotation = csvSource().lines("foo").textBlock(""" bar baz """).build(); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessage("@CsvSource must be declared with either `value` or `textBlock` but not both"); } @Test void providesSingleArgument() { var annotation = csvSource("foo"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo")); } @Test void providesSingleArgumentFromTextBlock() { var annotation = csvSource().textBlock("foo").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo")); } @Test void providesMultipleArguments() { var annotation = csvSource("foo", "bar"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesMultipleArgumentsFromTextBlock() { var annotation = csvSource().textBlock(""" foo bar """).build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void splitsAndTrimsArguments() { var annotation = csvSource(" foo , bar "); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo", "bar")); } @Test void trimsLeadingSpaces() { var annotation = csvSource("'', 1", " '', 2", "'' , 3", " '' , 4"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(new Object[][] { { "", "1" }, { "", "2" }, { "", "3" }, { "", "4" } }); } @Test void trimsTrailingSpaces() { var annotation = csvSource("1,''", "2, ''", "3,'' ", "4, '' "); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(new Object[][] { { "1", "" }, { "2", "" }, { "3", "" }, { "4", "" } }); } @Test void ignoresLeadingAndTrailingSpaces() { var annotation = csvSource().lines("1,a", "2, b", "3,c ", "4, d ") // .ignoreLeadingAndTrailingWhitespace(false).build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly( new Object[][] { { "1", "a" }, { "2", " b" }, { "3", "c " }, { "4", " d " } }); } @Test void understandsQuotes() { var annotation = csvSource("'foo, bar'"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo, bar")); } @Test void understandsQuotesInTextBlock() { var annotation = csvSource().textBlock(""" 'foo, bar' """).build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo, bar")); } @Test void understandsCustomQuotes() { var annotation = csvSource().quoteCharacter('~').lines("~foo, bar~").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo, bar")); } @Test void understandsCustomQuotesInTextBlock() { var annotation = csvSource().quoteCharacter('"').textBlock(""" "foo, bar" """).build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo, bar")); } @Test void understandsEscapeCharacters() { var annotation = csvSource("'foo or ''bar''', baz"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo or 'bar'", "baz")); } @Test void understandsEscapeCharactersWithCutomQuoteCharacter() { var annotation = csvSource().quoteCharacter('~').lines("~foo or ~~bar~~~, baz").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo or ~bar~", "baz")); } @Test void doesNotTrimSpacesInsideQuotes() { var annotation = csvSource("''", "' '", "'blank '", "' not blank '"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array(""), array(" "), array("blank "), array(" not blank ")); } @Test void providesArgumentsWithCharacterDelimiter() { var annotation = csvSource().delimiter('|').lines("foo|bar", "bar|foo").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo", "bar"), array("bar", "foo")); } @Test void providesArgumentsWithStringDelimiter() { var annotation = csvSource().delimiterString("~~~").lines("foo~~~ bar", "bar~~~ foo").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("foo", "bar"), array("bar", "foo")); } @Test void throwsExceptionIfBothDelimitersAreSimultaneouslySet() { var annotation = csvSource().delimiter('|').delimiterString("~~~").build(); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessageStartingWith("The delimiter and delimiterString attributes cannot be set simultaneously in")// .withMessageContaining("CsvSource"); } @Test void defaultEmptyValueAndDefaultNullValue() { var annotation = csvSource("'', null, , apple"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("", "null", null, "apple")); } @Test void customEmptyValueAndDefaultNullValue() { var annotation = csvSource().emptyValue("EMPTY").lines("'', null, , apple").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("EMPTY", "null", null, "apple")); } @Test void customNullValues() { var annotation = csvSource().nullValues("N/A", "NIL", "null")// .lines("apple, , NIL, '', N/A, banana, null").build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("apple", null, null, "", null, "banana", null)); } @Test void convertsEmptyValuesToNullInLinesAfterFirstLine() { var annotation = csvSource("'', ''", " , "); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(new Object[][] { { "", "" }, { null, null } }); } @Test void throwsExceptionIfSourceExceedsMaxCharsPerColumnConfig() { var annotation = csvSource().lines("413").maxCharsPerColumn(2).build(); assertThatExceptionOfType(CsvParsingException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessageStartingWith("Failed to parse CSV input configured via Mock for CsvSource")// .withRootCauseInstanceOf(ArrayIndexOutOfBoundsException.class); } @Test void providesArgumentWithDefaultMaxCharsPerColumnConfig() { var annotation = csvSource().lines("0".repeat(4096)).delimiter(';').build(); var arguments = provideArguments(annotation); assertThat(arguments.toArray()).hasSize(1); } @Test void throwsExceptionWhenSourceExceedsDefaultMaxCharsPerColumnConfig() { var annotation = csvSource().lines("0".repeat(4097)).delimiter(';').build(); assertThatExceptionOfType(CsvParsingException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessageStartingWith("Failed to parse CSV input configured via Mock for CsvSource")// .withRootCauseInstanceOf(ArrayIndexOutOfBoundsException.class); } @Test void providesArgumentsForExceedsSourceWithCustomMaxCharsPerColumnConfig() { var annotation = csvSource().lines("0".repeat(4097)).delimiter(';').maxCharsPerColumn(4097).build(); var arguments = provideArguments(annotation); assertThat(arguments.toArray()).hasSize(1); } @Test void throwsExceptionWhenMaxCharsPerColumnIsNotPositiveNumber() { var annotation = csvSource().lines("41").delimiter(';').maxCharsPerColumn(-1).build(); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessageStartingWith("maxCharsPerColumn must be a positive number: -1"); } @Test void ignoresCommentCharacterWhenUsingValueAttribute() { var annotation = csvSource("#foo", "#bar,baz", "baz,#quux"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("#foo"), array("#bar", "baz"), array("baz", "#quux")); } @Test void honorsCommentCharacterWhenUsingTextBlockAttribute() { var annotation = csvSource().textBlock(""" #foo bar, #baz '#bar', baz """).build(); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("bar", "#baz"), array("#bar", "baz")); } @Test void supportsCsvHeadersWhenUsingTextBlockAttribute() { supportsCsvHeaders(csvSource().useHeadersInDisplayName(true).textBlock(""" FRUIT, RANK apple, 1 banana, 2 """).build()); } @Test void supportsCsvHeadersWhenUsingValueAttribute() { supportsCsvHeaders(csvSource().useHeadersInDisplayName(true)// .lines("FRUIT, RANK", "apple, 1", "banana, 2").build()); } private void supportsCsvHeaders(CsvSource csvSource) { var arguments = provideArguments(csvSource); Stream argumentsAsStrings = arguments.map(array -> { String[] strings = new String[array.length]; for (int i = 0; i < array.length; i++) { strings[i] = String.valueOf(array[i]); } return strings; }); assertThat(argumentsAsStrings).containsExactly(array("FRUIT = apple", "RANK = 1"), array("FRUIT = banana", "RANK = 2")); } @Test void throwsExceptionIfColumnCountExceedsHeaderCount() { var annotation = csvSource().useHeadersInDisplayName(true).textBlock(""" FRUIT, RANK apple, 1 banana, 2, BOOM! """).build(); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> provideArguments(annotation))// .withMessage( "The number of columns (3) exceeds the number of supplied headers (2) in CSV record: [banana, 2, BOOM!]"); } private Stream provideArguments(CsvSource annotation) { var provider = new CsvArgumentsProvider(); provider.accept(annotation); return provider.provideArguments(mock()).map(Arguments::get); } @SuppressWarnings("unchecked") private static T[] array(T... elements) { return elements; } } CsvFileArgumentsProviderTests.java000066400000000000000000000423631455764576500373020ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.MockCsvAnnotationBuilder.csvFileSource; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.provider.CsvFileArgumentsProvider.InputStreamProvider; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; /** * @since 5.0 */ class CsvFileArgumentsProviderTests { @Test void providesArgumentsForNewlineAndComma() { var annotation = csvFileSource()// .resources("test.csv")// .lineSeparator("\n")// .delimiter(',')// .build(); var arguments = provideArguments(annotation, "foo, bar \n baz, qux \n"); assertThat(arguments).containsExactly(array("foo", "bar"), array("baz", "qux")); } @Test void providesArgumentsForCarriageReturnAndSemicolon() { var annotation = csvFileSource()// .resources("test.csv")// .lineSeparator("\r")// .delimiter(';')// .build(); var arguments = provideArguments(annotation, "foo; bar \r baz; qux"); assertThat(arguments).containsExactly(array("foo", "bar"), array("baz", "qux")); } @Test void providesArgumentsWithCustomQuoteCharacter() { var annotation = csvFileSource()// .resources("test.csv")// .quoteCharacter('\'')// .build(); var arguments = provideArguments(annotation, "foo, 'bar \"and\" baz', qux \n 'lemon lime', banana, apple"); assertThat(arguments).containsExactly(array("foo", "bar \"and\" baz", "qux"), array("lemon lime", "banana", "apple")); } @Test void providesArgumentsWithStringDelimiter() { var annotation = csvFileSource()// .resources("test.csv")// .delimiterString(",")// .build(); var arguments = provideArguments(annotation, "foo, bar \n baz, qux \n"); assertThat(arguments).containsExactly(array("foo", "bar"), array("baz", "qux")); } @Test void throwsExceptionIfBothDelimitersAreSimultaneouslySet() { var annotation = csvFileSource()// .resources("test.csv")// .delimiter(',')// .delimiterString(";")// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(annotation, "foo")); assertThat(exception)// .hasMessageStartingWith("The delimiter and delimiterString attributes cannot be set simultaneously in")// .hasMessageContaining("CsvFileSource"); } @Test void ignoresCommentedOutEntries() { var annotation = csvFileSource()// .resources("test.csv")// .delimiter(',')// .build(); var arguments = provideArguments(annotation, "foo, bar \n#baz, qux"); assertThat(arguments).containsExactly(array("foo", "bar")); } @Test void closesInputStreamForClasspathResource() { var closed = new AtomicBoolean(false); InputStream inputStream = new ByteArrayInputStream("foo".getBytes()) { @Override public void close() { closed.set(true); } }; var annotation = csvFileSource().resources("test.csv").build(); var arguments = provideArguments(inputStream, annotation); assertThat(arguments.count()).isEqualTo(1); assertThat(closed.get()).describedAs("closed").isTrue(); } @Test void closesInputStreamForFile(@TempDir Path tempDir) { var closed = new AtomicBoolean(false); InputStream inputStream = new ByteArrayInputStream("foo".getBytes()) { @Override public void close() { closed.set(true); } }; var annotation = csvFileSource().files(tempDir.resolve("test.csv").toAbsolutePath().toString()).build(); var arguments = provideArguments(inputStream, annotation); assertThat(arguments.count()).isEqualTo(1); assertThat(closed.get()).describedAs("closed").isTrue(); } @Test void readsFromSingleClasspathResource() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("baz"), array("qux"), array("")); } @Test void readsFromSingleFileWithAbsolutePath(@TempDir Path tempDir) throws Exception { var csvFile = writeClasspathResourceToFile("/single-column.csv", tempDir.resolve("single-column.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .files(csvFile.toAbsolutePath().toString())// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("baz"), array("qux"), array("")); } @Test void readsFromClasspathResourcesAndFiles(@TempDir Path tempDir) throws Exception { var csvFile = writeClasspathResourceToFile("/single-column.csv", tempDir.resolve("single-column.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .files(csvFile.toAbsolutePath().toString())// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).hasSize(2 * 5); } @Test void readsFromSingleFileWithRelativePath() throws Exception { var csvFile = writeClasspathResourceToFile("/single-column.csv", Path.of("single-column.csv")); try { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .files(csvFile.getFileName().toString())// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("baz"), array("qux"), array("")); } finally { Files.delete(csvFile); } } @Test void readsFromSingleClasspathResourceWithCustomEmptyValue() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .emptyValue("EMPTY")// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("baz"), array("qux"), array("EMPTY")); } @Test void readsFromMultipleClasspathResources() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv", "/single-column.csv")// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).hasSize(10); } @Test void readsFromSingleClasspathResourceWithHeaders() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .numLinesToSkip(1)// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("bar"), array("baz"), array("qux"), array("")); } @Test void readsFromSingleClasspathResourceWithMoreHeadersThanLines() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .numLinesToSkip(10)// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).isEmpty(); } @Test void readsFromMultipleClasspathResourcesWithHeaders() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv", "/single-column.csv")// .numLinesToSkip(1)// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).containsExactly(array("bar"), array("baz"), array("qux"), array(""), array("bar"), array("baz"), array("qux"), array("")); } @Test void supportsCsvHeadersInDisplayNames() { var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/single-column.csv")// .useHeadersInDisplayName(true)// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); Stream argumentsAsStrings = arguments.map(array -> new String[] { String.valueOf(array[0]) }); assertThat(argumentsAsStrings).containsExactly(array("foo = bar"), array("foo = baz"), array("foo = qux"), array("foo = ")); } @Test void throwsExceptionForMissingClasspathResource() { var annotation = csvFileSource()// .resources("/does-not-exist.csv")// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception).hasMessageContaining("Classpath resource [/does-not-exist.csv] does not exist"); } @Test void throwsExceptionForBlankClasspathResource() { var annotation = csvFileSource()// .resources(" ")// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception).hasMessageContaining("Classpath resource [ ] must not be null or blank"); } @Test void throwsExceptionForMissingFile() { var annotation = csvFileSource()// .files("does-not-exist.csv")// .build(); var exception = assertThrows(JUnitException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception).hasMessageContaining("File [does-not-exist.csv] could not be read"); } @Test void throwsExceptionForBlankFile() { var annotation = csvFileSource()// .files(" ")// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception).hasMessageContaining("File [ ] must not be null or blank"); } @Test void throwsExceptionIfResourcesAndFilesAreEmpty() { var annotation = csvFileSource()// .resources()// .files()// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception).hasMessageContaining("Resources or files must not be empty"); } @Test void throwsExceptionForInvalidCharset() { var annotation = csvFileSource()// .encoding("Bogus-Charset")// .resources("/bogus-charset.csv")// .build(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception)// .hasMessageContaining("The charset supplied in Mock for CsvFileSource")// .hasMessageEndingWith("is invalid"); } @Test void throwsExceptionForInvalidCsvFormat() { var annotation = csvFileSource()// .resources("/broken.csv")// .build(); var exception = assertThrows(CsvParsingException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception)// .hasMessageStartingWith("Failed to parse CSV input configured via Mock for CsvFileSource")// .hasRootCauseInstanceOf(ArrayIndexOutOfBoundsException.class); } @Test void emptyValueIsAnEmptyWithCustomNullValueString() { var annotation = csvFileSource()// .resources("test.csv")// .lineSeparator("\n")// .delimiter(',')// .nullValues("NIL")// .build(); var arguments = provideArguments(annotation, "apple, , NIL, ''\nNIL, NIL, foo, bar"); assertThat(arguments).containsExactly(array("apple", null, null, "''"), array(null, null, "foo", "bar")); } @Test void readsLineFromDefaultMaxCharsFileWithDefaultConfig(@TempDir Path tempDir) throws Exception { var csvFile = writeClasspathResourceToFile("/default-max-chars.csv", tempDir.resolve("default-max-chars.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/default-max-chars.csv")// .files(csvFile.toAbsolutePath().toString())// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).hasSize(2); } @Test void readsLineFromExceedsMaxCharsFileWithCustomConfig(@TempDir Path tempDir) throws java.io.IOException { var csvFile = writeClasspathResourceToFile("/exceeds-default-max-chars.csv", tempDir.resolve("exceeds-default-max-chars.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/exceeds-default-max-chars.csv")// .maxCharsPerColumn(4097)// .files(csvFile.toAbsolutePath().toString())// .build(); var arguments = provideArguments(new CsvFileArgumentsProvider(), annotation); assertThat(arguments).hasSize(2); } @Test void throwsExceptionWhenMaxCharsPerColumnIsNotPositiveNumber(@TempDir Path tempDir) throws java.io.IOException { var csvFile = writeClasspathResourceToFile("/exceeds-default-max-chars.csv", tempDir.resolve("exceeds-default-max-chars.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/exceeds-default-max-chars.csv")// .maxCharsPerColumn(-1).files(csvFile.toAbsolutePath().toString())// .build(); var exception = assertThrows(PreconditionViolationException.class, // () -> provideArguments(new CsvFileArgumentsProvider(), annotation)); assertThat(exception)// .hasMessageStartingWith("maxCharsPerColumn must be a positive number: -1"); } @Test void throwsExceptionForExceedsMaxCharsFileWithDefaultConfig(@TempDir Path tempDir) throws java.io.IOException { var csvFile = writeClasspathResourceToFile("/exceeds-default-max-chars.csv", tempDir.resolve("exceeds-default-max-chars.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/exceeds-default-max-chars.csv")// .files(csvFile.toAbsolutePath().toString())// .build(); var exception = assertThrows(CsvParsingException.class, () -> provideArguments(new CsvFileArgumentsProvider(), annotation).toArray()); assertThat(exception)// .hasMessageStartingWith("Failed to parse CSV input configured via Mock for CsvFileSource")// .hasRootCauseInstanceOf(ArrayIndexOutOfBoundsException.class); } @Test void ignoresLeadingAndTrailingSpaces(@TempDir Path tempDir) throws IOException { var csvFile = writeClasspathResourceToFile("/leading-trailing-spaces.csv", tempDir.resolve("leading-trailing-spaces.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/leading-trailing-spaces.csv")// .files(csvFile.toAbsolutePath().toString())// .ignoreLeadingAndTrailingWhitespace(true)// .build(); var arguments = provideArguments(new ByteArrayInputStream(Files.readAllBytes(csvFile)), annotation); assertThat(arguments).containsExactly(array("ab", "cd"), array("ef", "gh")); } @Test void trimsLeadingAndTrailingSpaces(@TempDir Path tempDir) throws IOException { var csvFile = writeClasspathResourceToFile("/leading-trailing-spaces.csv", tempDir.resolve("leading-trailing-spaces.csv")); var annotation = csvFileSource()// .encoding("ISO-8859-1")// .resources("/leading-trailing-spaces.csv")// .files(csvFile.toAbsolutePath().toString())// .delimiter(',')// .ignoreLeadingAndTrailingWhitespace(false)// .build(); var arguments = provideArguments(new ByteArrayInputStream(Files.readAllBytes(csvFile)), annotation); assertThat(arguments).containsExactly(array(" ab ", " cd"), array("ef ", "gh")); } private Stream provideArguments(CsvFileSource annotation, String content) { return provideArguments(new ByteArrayInputStream(content.getBytes(UTF_8)), annotation); } private Stream provideArguments(InputStream inputStream, CsvFileSource annotation) { var provider = new CsvFileArgumentsProvider(new InputStreamProvider() { @Override public InputStream openClasspathResource(Class baseClass, String path) { assertThat(path).isEqualTo(annotation.resources()[0]); return inputStream; } @Override public InputStream openFile(String path) { assertThat(path).isEqualTo(annotation.files()[0]); return inputStream; } }); return provideArguments(provider, annotation); } private Stream provideArguments(CsvFileArgumentsProvider provider, CsvFileSource annotation) { provider.accept(annotation); var context = mock(ExtensionContext.class); when(context.getTestClass()).thenReturn(Optional.of(CsvFileArgumentsProviderTests.class)); doCallRealMethod().when(context).getRequiredTestClass(); return provider.provideArguments(context).map(Arguments::get); } @SuppressWarnings("unchecked") private static T[] array(T... elements) { return elements; } private static Path writeClasspathResourceToFile(String name, Path target) throws IOException { try (var in = CsvFileArgumentsProviderTests.class.getResourceAsStream(name)) { Files.copy(in, target); } return target; } } EnumArgumentsProviderTests.java000066400000000000000000000114361455764576500366500ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.EnumArgumentsProviderTests.EnumWithTwoConstants.BAR; import static org.junit.jupiter.params.provider.EnumArgumentsProviderTests.EnumWithTwoConstants.FOO; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.provider.EnumSource.Mode; import org.junit.platform.commons.PreconditionViolationException; /** * @since 5.0 */ class EnumArgumentsProviderTests { private ExtensionContext extensionContext = mock(); @Test void providesAllEnumConstants() { var arguments = provideArguments(EnumWithTwoConstants.class); assertThat(arguments).containsExactly(new Object[] { FOO }, new Object[] { BAR }); } @Test void provideSingleEnumConstant() { var arguments = provideArguments(EnumWithTwoConstants.class, "FOO"); assertThat(arguments).containsExactly(new Object[] { FOO }); } @Test void provideAllEnumConstantsWithNamingAll() { var arguments = provideArguments(EnumWithTwoConstants.class, "FOO", "BAR"); assertThat(arguments).containsExactly(new Object[] { FOO }, new Object[] { BAR }); } @Test void duplicateConstantNameIsDetected() { Exception exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(EnumWithTwoConstants.class, "FOO", "BAR", "FOO")); assertThat(exception).hasMessageContaining("Duplicate enum constant name(s) found"); } @Test void invalidConstantNameIsDetected() { Exception exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(EnumWithTwoConstants.class, "FO0", "B4R")); assertThat(exception).hasMessageContaining("Invalid enum constant name(s) in"); } @Test void invalidPatternIsDetected() { Exception exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(EnumWithTwoConstants.class, Mode.MATCH_ALL, "(", ")")); assertThat(exception).hasMessageContaining("Pattern compilation failed"); } @Test void providesEnumConstantsBasedOnTestMethod() throws Exception { when(extensionContext.getRequiredTestMethod()).thenReturn( TestCase.class.getDeclaredMethod("methodWithCorrectParameter", EnumWithTwoConstants.class)); var arguments = provideArguments(NullEnum.class); assertThat(arguments).containsExactly(new Object[] { FOO }, new Object[] { BAR }); } @Test void incorrectParameterTypeIsDetected() throws Exception { when(extensionContext.getRequiredTestMethod()).thenReturn( TestCase.class.getDeclaredMethod("methodWithIncorrectParameter", Object.class)); Exception exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(NullEnum.class)); assertThat(exception).hasMessageStartingWith("First parameter must reference an Enum type"); } @Test void methodsWithoutParametersAreDetected() throws Exception { when(extensionContext.getRequiredTestMethod()).thenReturn( TestCase.class.getDeclaredMethod("methodWithoutParameters")); Exception exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(NullEnum.class)); assertThat(exception).hasMessageStartingWith("Test method must declare at least one parameter"); } static class TestCase { void methodWithCorrectParameter(EnumWithTwoConstants parameter) { } void methodWithIncorrectParameter(Object parameter) { } void methodWithoutParameters() { } } enum EnumWithTwoConstants { FOO, BAR } private > Stream provideArguments(Class enumClass, String... names) { return provideArguments(enumClass, Mode.INCLUDE, names); } private > Stream provideArguments(Class enumClass, Mode mode, String... names) { var annotation = mock(EnumSource.class); when(annotation.value()).thenAnswer(invocation -> enumClass); when(annotation.mode()).thenAnswer(invocation -> mode); when(annotation.names()).thenAnswer(invocation -> names); when(annotation.toString()).thenReturn(String.format("@EnumSource(value=%s.class, mode=%s, names=%s)", enumClass.getSimpleName(), mode, Arrays.toString(names))); var provider = new EnumArgumentsProvider(); provider.accept(annotation); return provider.provideArguments(extensionContext).map(Arguments::get); } } EnumSourceTests.java000066400000000000000000000102521455764576500344230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static java.util.stream.Collectors.toSet; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE; import static org.junit.jupiter.params.provider.EnumSource.Mode.INCLUDE; import static org.junit.jupiter.params.provider.EnumSource.Mode.MATCH_ALL; import static org.junit.jupiter.params.provider.EnumSource.Mode.MATCH_ANY; import static org.junit.jupiter.params.provider.EnumSource.Mode.MATCH_NONE; import static org.junit.jupiter.params.provider.EnumSourceTests.EnumWithThreeConstants.BAR; import static org.junit.jupiter.params.provider.EnumSourceTests.EnumWithThreeConstants.BAZ; import static org.junit.jupiter.params.provider.EnumSourceTests.EnumWithThreeConstants.FOO; import java.util.EnumSet; import java.util.Set; import java.util.function.Function; import org.junit.jupiter.api.Test; /** * @since 5.0 */ class EnumSourceTests { @Test void includeNamesWithAll() { assertAll("include names with all", // () -> assertTrue(INCLUDE.select(FOO, allOf(EnumWithThreeConstants::name))), () -> assertTrue(INCLUDE.select(BAR, allOf(EnumWithThreeConstants::name))), () -> assertTrue(INCLUDE.select(BAZ, allOf(EnumWithThreeConstants::name))) // ); } @Test void includeNamesWithSingleton() { assertAll("include names with singleton", // () -> assertTrue(INCLUDE.select(FOO, Set.of(FOO.name()))), () -> assertTrue(INCLUDE.select(BAR, Set.of(BAR.name()))), () -> assertTrue(INCLUDE.select(BAZ, Set.of(BAZ.name()))) // ); assertAll("include names with singleton complement", // () -> assertFalse(INCLUDE.select(BAR, Set.of(FOO.name()))), () -> assertFalse(INCLUDE.select(BAZ, Set.of(FOO.name()))) // ); } @Test void excludeNames() { assertAll("exclude name with none excluded", // () -> assertTrue(EXCLUDE.select(FOO, Set.of())), // () -> assertTrue(EXCLUDE.select(BAR, Set.of())), // () -> assertTrue(EXCLUDE.select(BAZ, Set.of())) // ); assertAll("exclude name with FOO excluded", // () -> assertFalse(EXCLUDE.select(FOO, Set.of(FOO.name()))), () -> assertTrue(EXCLUDE.select(BAR, Set.of(FOO.name()))), () -> assertTrue(EXCLUDE.select(BAZ, Set.of(FOO.name()))) // ); } @Test void matchesAll() { assertAll("matches all", // () -> assertTrue(MATCH_ALL.select(FOO, Set.of("F.."))), () -> assertTrue(MATCH_ALL.select(BAR, Set.of("B.."))), () -> assertTrue(MATCH_ALL.select(BAZ, Set.of("B.."))) // ); assertAll("matches all fails if not all match", // () -> assertFalse(MATCH_ALL.select(FOO, Set.of("F..", "."))), () -> assertFalse(MATCH_ALL.select(BAR, Set.of("B..", "."))), () -> assertFalse(MATCH_ALL.select(BAZ, Set.of("B..", "."))) // ); } @Test void matchesAny() { assertAll("matches any", // () -> assertTrue(MATCH_ANY.select(FOO, Set.of("B..", "^F.*"))), () -> assertTrue(MATCH_ANY.select(BAR, Set.of("B", "B.", "B.."))), () -> assertTrue(MATCH_ANY.select(BAZ, Set.of("^.+[zZ]$")))); } @Test void matchesNone() { assertAll("matches none fails if any match", // () -> assertFalse(MATCH_NONE.select(FOO, Set.of("F.."))), () -> assertFalse(MATCH_NONE.select(FOO, Set.of("B..", "F.."))), () -> assertFalse(MATCH_NONE.select(BAZ, Set.of("B.", "F.", "^.+[zZ]$")))); assertAll("matches none", // () -> assertTrue(MATCH_NONE.select(FOO, Set.of())), // () -> assertTrue(MATCH_NONE.select(FOO, Set.of("F."))), () -> assertTrue(MATCH_NONE.select(FOO, Set.of("B.."))), () -> assertTrue(MATCH_NONE.select(BAZ, Set.of(".", "B.", "F.")))); } enum EnumWithThreeConstants { FOO, BAR, BAZ; } static Set allOf(Function mapper) { return EnumSet.allOf(EnumWithThreeConstants.class).stream().map(mapper).collect(toSet()); } } MethodArgumentsProviderTests.java000066400000000000000000001076501455764576500371700ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.engine.extension.MutableExtensionRegistry.createRegistryWithDefaultExtensions; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.execution.DefaultExecutableInvoker; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.jupiter.params.ParameterizedTest; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 5.0 */ class MethodArgumentsProviderTests { private MutableExtensionRegistry extensionRegistry; @Test void providesArgumentsUsingStream() { var arguments = provideArguments("stringStreamProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingDoubleStream() { var arguments = provideArguments("doubleStreamProvider"); assertThat(arguments).containsExactly(array(1.2), array(3.4)); } @Test void providesArgumentsUsingLongStream() { var arguments = provideArguments("longStreamProvider"); assertThat(arguments).containsExactly(array(1L), array(2L)); } @Test void providesArgumentsUsingIntStream() { var arguments = provideArguments("intStreamProvider"); assertThat(arguments).containsExactly(array(1), array(2)); } /** * @since 5.3.2 */ @Test void providesArgumentsUsingStreamOfIntArrays() { var arguments = provideArguments("intArrayStreamProvider"); assertThat(arguments).containsExactly( // new Object[] { new int[] { 1, 2 } }, // new Object[] { new int[] { 3, 4 } } // ); } /** * @since 5.3.2 */ @Test void providesArgumentsUsingStreamOfTwoDimensionalIntArrays() { var arguments = provideArguments("twoDimensionalIntArrayStreamProvider"); assertThat(arguments).containsExactly( // array((Object) new int[][] { { 1, 2 }, { 2, 3 } }), // array((Object) new int[][] { { 4, 5 }, { 5, 6 } }) // ); } @Test void providesArgumentsUsingStreamOfObjectArrays() { var arguments = provideArguments("objectArrayStreamProvider"); assertThat(arguments).containsExactly(array("foo", 42), array("bar", 23)); } /** * @since 5.3.2 */ @Test void providesArgumentsUsingStreamOfTwoDimensionalObjectArrays() { var arguments = provideArguments("twoDimensionalObjectArrayStreamProvider"); assertThat(arguments).containsExactly( // array((Object) array(array("a", 1), array("b", 2))), // array((Object) array(array("c", 3), array("d", 4))) // ); } @Test void providesArgumentsUsingStreamOfArguments() { var arguments = provideArguments("argumentsStreamProvider"); assertThat(arguments).containsExactly(array("foo", 42), array("bar", 23)); } @Test void providesArgumentsUsingIterable() { var arguments = provideArguments("stringIterableProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingIterator() { var arguments = provideArguments("stringIteratorProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingMultipleFactoryMethods() { var arguments = provideArguments("stringStreamProvider", "stringIterableProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("foo"), array("bar")); } @Test void providesArgumentsUsingIterableOfObjectArrays() { var arguments = provideArguments("objectArrayIterableProvider"); assertThat(arguments).containsExactly(array("foo", 42), array("bar", 23)); } @Test void providesArgumentsUsingListOfStrings() { var arguments = provideArguments("stringArrayListProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingListOfObjectArrays() { var arguments = provideArguments("objectArrayListProvider"); assertThat(arguments).containsExactly(array("foo", 42), array("bar", 23)); } @Test void throwsExceptionWhenNonStaticLocalFactoryMethodIsReferencedWithLifecyclePerMethodSemantics() { var lifecyclePerClass = false; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(NonStaticTestCase.class, lifecyclePerClass, "nonStaticStringStreamProvider").toArray()); assertStaticIsRequired(exception); } @Test void throwsExceptionWhenNonStaticExternalFactoryMethodIsReferencedWithLifecyclePerMethodSemantics() { var factoryClass = NonStaticTestCase.class.getName(); var factoryMethod = factoryClass + "#nonStaticStringStreamProvider"; var lifecyclePerClass = false; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(TestCase.class, lifecyclePerClass, factoryMethod).toArray()); assertStaticIsRequired(exception); } @Test void throwsExceptionWhenNonStaticExternalFactoryMethodIsReferencedWithLifecyclePerClassSemantics() { var factoryClass = NonStaticTestCase.class.getName(); var factoryMethod = factoryClass + "#nonStaticStringStreamProvider"; boolean lifecyclePerClass = true; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(TestCase.class, lifecyclePerClass, factoryMethod).toArray()); assertStaticIsRequired(exception); } private static void assertStaticIsRequired(PreconditionViolationException exception) { assertThat(exception).hasMessageContainingAll("Method '", "' must be static: local factory methods must be static ", "unless the PER_CLASS @TestInstance lifecycle mode is used; ", "external factory methods must always be static."); } @Test void providesArgumentsFromNonStaticFactoryMethodWhenStaticIsNotRequired() { var arguments = provideArguments(NonStaticTestCase.class, true, "nonStaticStringStreamProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingDefaultFactoryMethodName() { var testClass = DefaultFactoryMethodNameTestCase.class; var methodName = "testDefaultFactoryMethodName"; var testMethod = findMethod(testClass, methodName, String.class).get(); var arguments = provideArguments(testClass, testMethod, false, ""); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingExternalFactoryMethod() { var arguments = provideArguments(ExternalFactoryMethods.class.getName() + "#stringsProvider"); assertThat(arguments).containsExactly(array("string1"), array("string2")); } @Test void providesArgumentsUsingExternalFactoryMethodInTypeFromDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(TestCase.class, ExternalFactoryMethods.class)) { var testClass = testClassLoader.loadClass(TestCase.class.getName()); var testMethod = ReflectionUtils.findMethod(testClass, "test").get(); var fullyQualifiedMethodName = ExternalFactoryMethods.class.getName() + "#stringsProvider"; assertThat(testClass.getClassLoader()).isSameAs(testClassLoader); var arguments = provideArguments(testClass, false, fullyQualifiedMethodName); assertThat(arguments).containsExactly(array("string1"), array("string2")); var factoryMethod = MethodArgumentsProvider.findFactoryMethodByFullyQualifiedName(testClass, testMethod, fullyQualifiedMethodName); assertThat(factoryMethod).isNotNull(); assertThat(factoryMethod.getName()).isEqualTo("stringsProvider"); assertThat(factoryMethod.getParameterTypes()).isEmpty(); var declaringClass = factoryMethod.getDeclaringClass(); assertThat(declaringClass.getName()).isEqualTo(ExternalFactoryMethods.class.getName()); assertThat(declaringClass).isNotEqualTo(ExternalFactoryMethods.class); assertThat(declaringClass.getClassLoader()).isSameAs(testClassLoader); } } @Test void providesArgumentsUsingExternalFactoryMethodWithParentheses() { var arguments = provideArguments(ExternalFactoryMethods.class.getName() + "#stringsProvider()"); assertThat(arguments).containsExactly(array("string1"), array("string2")); } @Test void providesArgumentsUsingExternalFactoryMethodFromStaticNestedClass() { var arguments = provideArguments(ExternalFactoryMethods.class.getName() + "$Nested#stringsProvider()"); assertThat(arguments).containsExactly(array("nested string1"), array("nested string2")); } @Test void providesArgumentsUsingExternalAndInternalFactoryMethodsCombined() { var arguments = provideArguments("stringStreamProvider", ExternalFactoryMethods.class.getName() + "#stringsProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar"), array("string1"), array("string2")); } @Nested class PrimitiveArrays { @Test void providesArgumentsUsingBooleanArray() { var arguments = provideArguments("booleanArrayProvider"); assertThat(arguments).containsExactly(array(Boolean.TRUE), array(Boolean.FALSE)); } @Test void providesArgumentsUsingByteArray() { var arguments = provideArguments("byteArrayProvider"); assertThat(arguments).containsExactly(array((byte) 1), array(Byte.MIN_VALUE)); } @Test void providesArgumentsUsingCharArray() { var arguments = provideArguments("charArrayProvider"); assertThat(arguments).containsExactly(array((char) 1), array(Character.MIN_VALUE)); } @Test void providesArgumentsUsingDoubleArray() { var arguments = provideArguments("doubleArrayProvider"); assertThat(arguments).containsExactly(array(1d), array(Double.MIN_VALUE)); } @Test void providesArgumentsUsingFloatArray() { var arguments = provideArguments("floatArrayProvider"); assertThat(arguments).containsExactly(array(1f), array(Float.MIN_VALUE)); } @Test void providesArgumentsUsingIntArray() { var arguments = provideArguments("intArrayProvider"); assertThat(arguments).containsExactly(array(47), array(Integer.MIN_VALUE)); } @Test void providesArgumentsUsingLongArray() { var arguments = provideArguments("longArrayProvider"); assertThat(arguments).containsExactly(array(47L), array(Long.MIN_VALUE)); } @Test void providesArgumentsUsingShortArray() { var arguments = provideArguments("shortArrayProvider"); assertThat(arguments).containsExactly(array((short) 47), array(Short.MIN_VALUE)); } } @Nested class ObjectArrays { @Test void providesArgumentsUsingObjectArray() { var arguments = provideArguments("objectArrayProvider"); assertThat(arguments).containsExactly(array(42), array("bar")); } @Test void providesArgumentsUsingStringArray() { var arguments = provideArguments("stringArrayProvider"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsing2dObjectArray() { var arguments = provideArguments("twoDimensionalObjectArrayProvider"); assertThat(arguments).containsExactly(array("foo", 42), array("bar", 23)); } } @Nested class ParameterResolution { private final Method testMethod = findMethod(TestCase.class, "test").get(); @BeforeEach void registerParameterResolver() { extensionRegistry = createRegistryWithDefaultExtensions(mock()); extensionRegistry.registerExtension(StringResolver.class); extensionRegistry.registerExtension(StringArrayResolver.class); extensionRegistry.registerExtension(IntArrayResolver.class); } @Test void providesArgumentsInferringDefaultFactoryMethodThatAcceptsArgument() { Method testMethod = findMethod(TestCase.class, "overloadedStringStreamProvider", Object.class).get(); String factoryMethodName = ""; // signals to use default var arguments = provideArguments(testMethod, factoryMethodName); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingSimpleNameForFactoryMethodThatAcceptsArgumentWithoutSpecifyingParameterList() { var arguments = provideArguments("stringStreamProviderWithParameter"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingFullyQualifiedNameForFactoryMethodThatAcceptsArgumentWithoutSpecifyingParameterList() { var arguments = provideArguments(TestCase.class.getName() + "#stringStreamProviderWithParameter"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingFullyQualifiedNameSpecifyingParameter() { var arguments = provideArguments( TestCase.class.getName() + "#stringStreamProviderWithParameter(java.lang.String)"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingLocalQualifiedNameSpecifyingParameter() { var arguments = provideArguments(testMethod, "stringStreamProviderWithParameter(java.lang.String)"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingFullyQualifiedNameForOverloadedFactoryMethodSpecifyingEmptyParameterList() { var arguments = provideArguments( TestCase.class.getName() + "#stringStreamProviderWithOrWithoutParameter()"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingLocalQualifiedNameForOverloadedFactoryMethodSpecifyingEmptyParameterList() { var arguments = provideArguments(this.testMethod, "stringStreamProviderWithOrWithoutParameter()"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingFullyQualifiedNameForOverloadedFactoryMethodSpecifyingParameter() { var arguments = provideArguments( TestCase.class.getName() + "#stringStreamProviderWithOrWithoutParameter(java.lang.String)"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void providesArgumentsUsingLocalQualifiedNameForOverloadedFactoryMethodSpecifyingParameter() { var arguments = provideArguments(testMethod, "stringStreamProviderWithOrWithoutParameter(java.lang.String)"); assertThat(arguments).containsExactly(array("foo!"), array("bar!")); } @Test void failsToProvideArgumentsUsingFullyQualifiedNameSpecifyingInvalidParameterType() { String method = TestCase.class.getName() + "#stringStreamProviderWithParameter(example.FooBar)"; var exception = assertThrows(JUnitException.class, () -> provideArguments(method).toArray()); assertThat(exception).hasMessage(""" Failed to load parameter type [example.FooBar] for method [stringStreamProviderWithParameter] \ in class [org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase]."""); } @Test void failsToProvideArgumentsUsingLocalQualifiedNameSpecifyingInvalidParameterType() { var method = "stringStreamProviderWithParameter(example.FooBar)"; var exception = assertThrows(JUnitException.class, () -> provideArguments(this.testMethod, method).toArray()); assertThat(exception).hasMessage(""" Failed to load parameter type [example.FooBar] for method [stringStreamProviderWithParameter] \ in class [org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase]."""); } @Test void failsToProvideArgumentsUsingFullyQualifiedNameSpecifyingIncorrectParameterType() { String method = TestCase.class.getName() + "#stringStreamProviderWithParameter(java.lang.Integer)"; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(method).toArray()); assertThat(exception).hasMessage(""" Could not find factory method [stringStreamProviderWithParameter(java.lang.Integer)] in \ class [org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase]"""); } @Test void failsToProvideArgumentsUsingLocalQualifiedNameSpecifyingIncorrectParameterType() { var method = "stringStreamProviderWithParameter(java.lang.Integer)"; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(this.testMethod, method).toArray()); assertThat(exception).hasMessage(""" Could not find factory method [stringStreamProviderWithParameter(java.lang.Integer)] in \ class [org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase]"""); } @ParameterizedTest @ValueSource(strings = { "org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase#stringStreamProviderWithArrayParameter(java.lang.String[])", "org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase#stringStreamProviderWithArrayParameter([Ljava.lang.String;)", }) void providesArgumentsUsingFullyQualifiedNameSpecifyingObjectArrayParameter(String method) { var arguments = provideArguments(method); assertThat(arguments).containsExactly(array("foo :)"), array("bar :)")); } @ParameterizedTest @ValueSource(strings = { // "stringStreamProviderWithArrayParameter(java.lang.String[])", "stringStreamProviderWithArrayParameter([Ljava.lang.String;)" }) void providesArgumentsUsingLocalQualifiedNameSpecifyingObjectArrayParameter(String method) { var arguments = provideArguments(this.testMethod, method); assertThat(arguments).containsExactly(array("foo :)"), array("bar :)")); } @ParameterizedTest @ValueSource(strings = { "org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase#stringStreamProviderWithArrayParameter(int[])", "org.junit.jupiter.params.provider.MethodArgumentsProviderTests$TestCase#stringStreamProviderWithArrayParameter([I)", }) void providesArgumentsUsingFullyQualifiedNameSpecifyingPrimitiveArrayParameter(String method) { var arguments = provideArguments(method); assertThat(arguments).containsExactly(array("foo 42"), array("bar 42")); } @ParameterizedTest @ValueSource(strings = { // "stringStreamProviderWithArrayParameter(int[])", // "stringStreamProviderWithArrayParameter([I)" }) void providesArgumentsUsingLocalQualifiedNameSpecifyingPrimitiveArrayParameter(String method) { var arguments = provideArguments(this.testMethod, method); assertThat(arguments).containsExactly(array("foo 42"), array("bar 42")); } @ParameterizedTest @ValueSource(strings = { "java.lang.String,java.lang.String", "java.lang.String, java.lang.String", "java.lang.String, java.lang.String" }) void providesArgumentsUsingFullyQualifiedNameSpecifyingMultipleParameters(String params) { var method = TestCase.class.getName() + "#stringStreamProviderWithOrWithoutParameter(" + params + ")"; var arguments = provideArguments(method); assertThat(arguments).containsExactly(array("foo!!"), array("bar!!")); } @ParameterizedTest @ValueSource(strings = { "java.lang.String,java.lang.String", "java.lang.String, java.lang.String", "java.lang.String, java.lang.String" }) void providesArgumentsUsingLocalQualifiedNameSpecifyingMultipleParameters(String params) { var arguments = provideArguments(this.testMethod, "stringStreamProviderWithOrWithoutParameter(" + params + ")"); assertThat(arguments).containsExactly(array("foo!!"), array("bar!!")); } @Test void providesArgumentsUsingFullyQualifiedNameForOverloadedFactoryMethodWhenParameterListIsNotSpecified() { var arguments = provideArguments(TestCase.class.getName() + "#stringStreamProviderWithOrWithoutParameter"); assertThat(arguments).containsExactly(array("foo"), array("bar")); } @Test void providesArgumentsUsingLocalQualifiedNameForOverloadedFactoryMethodWhenParameterListIsNotSpecified() { var arguments = provideArguments("stringStreamProviderWithOrWithoutParameter").toArray(); assertThat(arguments).containsExactly(array("foo"), array("bar")); } } @Nested class ErrorCases { @Test void throwsExceptionWhenFullyQualifiedMethodNameSyntaxIsInvalid() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments("org.example.wrongSyntax").toArray()); assertThat(exception.getMessage()).isEqualTo( "[org.example.wrongSyntax] is not a valid fully qualified method name: " + "it must start with a fully qualified class name followed by a '#' and then the method name, " + "optionally followed by a parameter list enclosed in parentheses."); } @Test void throwsExceptionWhenClassForExternalFactoryMethodCannotBeLoaded() { var exception = assertThrows(JUnitException.class, () -> provideArguments("com.example.NonExistentClass#stringsProvider").toArray()); assertThat(exception.getMessage()).isEqualTo("Could not load class [com.example.NonExistentClass]"); } @Test void throwsExceptionWhenExternalFactoryMethodDoesNotExist() { String factoryClass = ExternalFactoryMethods.class.getName(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(factoryClass + "#nonExistentMethod").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod] in class [%s]", factoryClass); } @Test void throwsExceptionWhenLocalFactoryMethodDoesNotExist() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments("nonExistentMethod").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod] in class [%s]", TestCase.class.getName()); } @Test void throwsExceptionWhenExternalFactoryMethodAcceptingSingleArgumentDoesNotExist() { String factoryClass = ExternalFactoryMethods.class.getName(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(factoryClass + "#nonExistentMethod(int)").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod(int)] in class [%s]", factoryClass); } @Test void throwsExceptionWhenLocalFactoryMethodAcceptingSingleArgumentDoesNotExist() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments("nonExistentMethod(int)").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod(int)] in class [%s]", TestCase.class.getName()); } @Test void throwsExceptionWhenExternalFactoryMethodAcceptingMultipleArgumentsDoesNotExist() { String factoryClass = ExternalFactoryMethods.class.getName(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(factoryClass + "#nonExistentMethod(int, java.lang.String)").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod(int, java.lang.String)] in class [%s]", factoryClass); } @Test void throwsExceptionWhenLocalFactoryMethodAcceptingMultipleArgumentsDoesNotExist() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments("nonExistentMethod(java.lang.String,int)").toArray()); assertThat(exception.getMessage()).isEqualTo( "Could not find factory method [nonExistentMethod(java.lang.String,int)] in class [%s]", TestCase.class.getName()); } @Test void throwsExceptionWhenExternalFactoryMethodHasInvalidReturnType() { String testClass = TestCase.class.getName(); String factoryClass = ExternalFactoryMethods.class.getName(); String factoryMethod = factoryClass + "#factoryWithInvalidReturnType"; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(TestCase.class, false, factoryMethod).toArray()); assertThat(exception.getMessage())// .containsSubsequence("Could not find valid factory method [" + factoryMethod + "] for test class [", testClass + "]", // "but found the following invalid candidate: ", "static java.lang.Object " + factoryClass + ".factoryWithInvalidReturnType()"); } @Test void throwsExceptionWhenLocalFactoryMethodHasInvalidReturnType() { String testClass = TestCase.class.getName(); String factoryClass = testClass; String factoryMethod = "factoryWithInvalidReturnType"; var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(factoryMethod).toArray()); assertThat(exception.getMessage())// .containsSubsequence("Could not find valid factory method [" + factoryMethod + "] for test class [", factoryClass + "]", // "but found the following invalid candidate: ", // "static java.lang.Object " + factoryClass + ".factoryWithInvalidReturnType()"); } @Test void throwsExceptionWhenMultipleDefaultFactoryMethodCandidatesExist() { var testClass = MultipleDefaultFactoriesTestCase.class; var methodName = "test"; var testMethod = findMethod(testClass, methodName, String.class).get(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(testClass, testMethod, false, "").toArray()); assertThat(exception.getMessage()).contains(// "2 factory methods named [test] were found in class [", testClass.getName() + "]: ", // "$MultipleDefaultFactoriesTestCase.test()", // "$MultipleDefaultFactoriesTestCase.test(int)"// ); } @Test void throwsExceptionWhenMultipleInvalidDefaultFactoryMethodCandidatesExist() { var testClass = MultipleInvalidDefaultFactoriesTestCase.class; var methodName = "test"; var testMethod = findMethod(testClass, methodName, String.class).get(); var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(testClass, testMethod, false, "").toArray()); assertThat(exception.getMessage()).contains(// "Could not find valid factory method [test] in class [", testClass.getName() + "]", // "but found the following invalid candidates: ", // "$MultipleInvalidDefaultFactoriesTestCase.test()", // "$MultipleInvalidDefaultFactoriesTestCase.test(int)"// ); } } // ------------------------------------------------------------------------- private static Object[] array(Object... objects) { return objects; } private Stream provideArguments(String... factoryMethodNames) { return provideArguments(TestCase.class, false, factoryMethodNames); } private Stream provideArguments(Method testMethod, String factoryMethodName) { return provideArguments(TestCase.class, testMethod, false, factoryMethodName); } private Stream provideArguments(Class testClass, boolean allowNonStaticMethod, String... factoryMethodNames) { // Ensure we have a non-null test method, even if it's not a real test method. // If this throws an exception, make sure that the supplied test class defines a "void test()" method. Method testMethod = ReflectionUtils.findMethod(testClass, "test").get(); return provideArguments(testClass, testMethod, allowNonStaticMethod, factoryMethodNames); } private Stream provideArguments(Class testClass, Method testMethod, boolean allowNonStaticMethod, String... factoryMethodNames) { var methodSource = mock(MethodSource.class); when(methodSource.value()).thenReturn(factoryMethodNames); var extensionContext = mock(ExtensionContext.class); when(extensionContext.getTestClass()).thenReturn(Optional.of(testClass)); when(extensionContext.getTestMethod()).thenReturn(Optional.of(testMethod)); when(extensionContext.getExecutableInvoker()).thenReturn( new DefaultExecutableInvoker(extensionContext, extensionRegistry)); doCallRealMethod().when(extensionContext).getRequiredTestMethod(); doCallRealMethod().when(extensionContext).getRequiredTestClass(); var testInstance = allowNonStaticMethod ? ReflectionUtils.newInstance(testClass) : null; when(extensionContext.getTestInstance()).thenReturn(Optional.ofNullable(testInstance)); var lifeCycle = allowNonStaticMethod ? Lifecycle.PER_CLASS : Lifecycle.PER_METHOD; when(extensionContext.getTestInstanceLifecycle()).thenReturn(Optional.of(lifeCycle)); var provider = new MethodArgumentsProvider(); provider.accept(methodSource); return provider.provideArguments(extensionContext).map(Arguments::get); } // ------------------------------------------------------------------------- static class DefaultFactoryMethodNameTestCase { // Test void testDefaultFactoryMethodName(String param) { } // Factory static Stream testDefaultFactoryMethodName() { return Stream.of("foo", "bar"); } } static class MultipleDefaultFactoriesTestCase { // Test void test(String param) { } // Factory static Stream test() { return Stream.of(); } // Another Factory static Stream test(int num) { return Stream.of(); } } static class MultipleInvalidDefaultFactoriesTestCase { // Test void test(String param) { } // NOT a Factory static String test() { return null; } // Also NOT a Factory static Object test(int num) { return null; } } static class TestCase { void test() { } // --- Invalid --------------------------------------------------------- static Object factoryWithInvalidReturnType() { return -1; } // --- Stream ---------------------------------------------------------- static Stream stringStreamProvider() { return Stream.of("foo", "bar"); } static Stream stringStreamProviderWithParameter(String parameter) { return Stream.of("foo" + parameter, "bar" + parameter); } static Stream stringStreamProviderWithArrayParameter(String[] parameter) { String suffix = Arrays.stream(parameter).collect(Collectors.joining()); return Stream.of("foo " + suffix, "bar " + suffix); } static Stream stringStreamProviderWithArrayParameter(int[] parameter) { return stringStreamProviderWithArrayParameter( Arrays.stream(parameter).mapToObj(String::valueOf).toArray(String[]::new)); } static Stream stringStreamProviderWithOrWithoutParameter() { return stringStreamProvider(); } static Stream stringStreamProviderWithOrWithoutParameter(String parameter) { return stringStreamProviderWithParameter(parameter); } static Stream stringStreamProviderWithOrWithoutParameter(String parameter1, String parameter2) { return stringStreamProviderWithParameter(parameter1 + parameter2); } // Overloaded method, but not a valid return type for a factory method static void stringStreamProviderWithOrWithoutParameter(String parameter1, int parameter2) { } // @ParameterizedTest // @MethodSource // use default, inferred factory method void overloadedStringStreamProvider(Object parameter) { // test implementation } // Default factory method for overloadedStringStreamProvider(Object) static Stream overloadedStringStreamProvider(String parameter) { return stringStreamProviderWithParameter(parameter); } static DoubleStream doubleStreamProvider() { return DoubleStream.of(1.2, 3.4); } static LongStream longStreamProvider() { return LongStream.of(1L, 2L); } static IntStream intStreamProvider() { return IntStream.of(1, 2); } static Stream intArrayStreamProvider() { return Stream.of(new int[] { 1, 2 }, new int[] { 3, 4 }); } static Stream twoDimensionalIntArrayStreamProvider() { return Stream.of(new int[][] { { 1, 2 }, { 2, 3 } }, new int[][] { { 4, 5 }, { 5, 6 } }); } static Stream objectArrayStreamProvider() { return Stream.of(new Object[] { "foo", 42 }, new Object[] { "bar", 23 }); } static Stream twoDimensionalObjectArrayStreamProvider() { return Stream.of(new Object[][] { { "a", 1 }, { "b", 2 } }, new Object[][] { { "c", 3 }, { "d", 4 } }); } static Stream argumentsStreamProvider() { return objectArrayStreamProvider().map(Arguments::of); } // --- Iterable / Collection ------------------------------------------- static Iterable stringIterableProvider() { return TestCase::stringIteratorProvider; } static Iterable objectArrayIterableProvider() { return objectArrayListProvider(); } static List stringArrayListProvider() { return Arrays.asList("foo", "bar"); } static List objectArrayListProvider() { return Arrays.asList(array("foo", 42), array("bar", 23)); } // --- Iterator -------------------------------------------------------- static Iterator stringIteratorProvider() { return Arrays.asList("foo", "bar").iterator(); } // --- Array of primitives --------------------------------------------- static boolean[] booleanArrayProvider() { return new boolean[] { true, false }; } static byte[] byteArrayProvider() { return new byte[] { (byte) 1, Byte.MIN_VALUE }; } static char[] charArrayProvider() { return new char[] { (char) 1, Character.MIN_VALUE }; } static double[] doubleArrayProvider() { return new double[] { 1d, Double.MIN_VALUE }; } static float[] floatArrayProvider() { return new float[] { 1f, Float.MIN_VALUE }; } static int[] intArrayProvider() { return new int[] { 47, Integer.MIN_VALUE }; } static long[] longArrayProvider() { return new long[] { 47L, Long.MIN_VALUE }; } static short[] shortArrayProvider() { return new short[] { (short) 47, Short.MIN_VALUE }; } // --- Array of objects ------------------------------------------------ static Object[] objectArrayProvider() { return new Object[] { 42, "bar" }; } static String[] stringArrayProvider() { return new String[] { "foo", "bar" }; } static Object[][] twoDimensionalObjectArrayProvider() { return new Object[][] { { "foo", 42 }, { "bar", 23 } }; } } // This test case mimics @TestInstance(Lifecycle.PER_CLASS) static class NonStaticTestCase { void test() { } Stream nonStaticStringStreamProvider() { return Stream.of("foo", "bar"); } } static class ExternalFactoryMethods { static Object factoryWithInvalidReturnType() { return -1; } static Stream stringsProvider() { return Stream.of("string1", "string2"); } static class Nested { static Stream stringsProvider() { return Stream.of("nested string1", "nested string2"); } } } static class StringResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == String.class; } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return "!"; } } static class StringArrayResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == String[].class; } @Override public String[] resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return new String[] { ":", ")" }; } } static class IntArrayResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return parameterContext.getParameter().getType() == int[].class; } @Override public int[] resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return new int[] { 4, 2 }; } } } MockCsvAnnotationBuilder.java000066400000000000000000000134071455764576500362270ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.lang.annotation.Annotation; /** * @since 5.6 */ abstract class MockCsvAnnotationBuilder> { static CsvSource csvSource(String... lines) { return csvSource().lines(lines).build(); } static MockCsvSourceBuilder csvSource() { return new MockCsvSourceBuilder(); } static MockCsvFileSourceBuilder csvFileSource() { return new MockCsvFileSourceBuilder(); } // ------------------------------------------------------------------------- private boolean useHeadersInDisplayName = false; private char quoteCharacter = '\0'; protected char delimiter = '\0'; protected String delimiterString = ""; protected String emptyValue = ""; protected String[] nullValues = new String[0]; protected int maxCharsPerColumn = 4096; protected boolean ignoreLeadingAndTrailingWhitespace = true; private MockCsvAnnotationBuilder() { } protected abstract B getSelf(); B useHeadersInDisplayName(boolean useHeadersInDisplayName) { this.useHeadersInDisplayName = useHeadersInDisplayName; return getSelf(); } B quoteCharacter(char quoteCharacter) { this.quoteCharacter = quoteCharacter; return getSelf(); } B delimiter(char delimiter) { this.delimiter = delimiter; return getSelf(); } B delimiterString(String delimiterString) { this.delimiterString = delimiterString; return getSelf(); } B emptyValue(String emptyValue) { this.emptyValue = emptyValue; return getSelf(); } B nullValues(String... nullValues) { this.nullValues = nullValues; return getSelf(); } B maxCharsPerColumn(int maxCharsPerColumn) { this.maxCharsPerColumn = maxCharsPerColumn; return getSelf(); } B ignoreLeadingAndTrailingWhitespace(boolean ignoreLeadingAndTrailingWhitespace) { this.ignoreLeadingAndTrailingWhitespace = ignoreLeadingAndTrailingWhitespace; return getSelf(); } abstract A build(); // ------------------------------------------------------------------------- static class MockCsvSourceBuilder extends MockCsvAnnotationBuilder { private String[] lines = new String[0]; private String textBlock = ""; private MockCsvSourceBuilder() { super.quoteCharacter = '\''; } @Override protected MockCsvSourceBuilder getSelf() { return this; } MockCsvSourceBuilder lines(String... lines) { this.lines = lines; return this; } MockCsvSourceBuilder textBlock(String textBlock) { this.textBlock = textBlock; return this; } @Override CsvSource build() { var annotation = mock(CsvSource.class); // Common when(annotation.useHeadersInDisplayName()).thenReturn(super.useHeadersInDisplayName); when(annotation.quoteCharacter()).thenReturn(super.quoteCharacter); when(annotation.delimiter()).thenReturn(super.delimiter); when(annotation.delimiterString()).thenReturn(super.delimiterString); when(annotation.emptyValue()).thenReturn(super.emptyValue); when(annotation.nullValues()).thenReturn(super.nullValues); when(annotation.maxCharsPerColumn()).thenReturn(super.maxCharsPerColumn); when(annotation.ignoreLeadingAndTrailingWhitespace()).thenReturn(super.ignoreLeadingAndTrailingWhitespace); // @CsvSource when(annotation.value()).thenReturn(this.lines); when(annotation.textBlock()).thenReturn(this.textBlock); return annotation; } } static class MockCsvFileSourceBuilder extends MockCsvAnnotationBuilder { private String[] resources = {}; private String[] files = {}; private String encoding = "UTF-8"; private String lineSeparator = "\n"; private int numLinesToSkip = 0; private MockCsvFileSourceBuilder() { super.quoteCharacter = '"'; } @Override protected MockCsvFileSourceBuilder getSelf() { return this; } MockCsvFileSourceBuilder resources(String... resources) { this.resources = resources; return this; } MockCsvFileSourceBuilder files(String... files) { this.files = files; return this; } MockCsvFileSourceBuilder encoding(String encoding) { this.encoding = encoding; return this; } MockCsvFileSourceBuilder lineSeparator(String lineSeparator) { this.lineSeparator = lineSeparator; return this; } MockCsvFileSourceBuilder numLinesToSkip(int numLinesToSkip) { this.numLinesToSkip = numLinesToSkip; return this; } @Override CsvFileSource build() { var annotation = mock(CsvFileSource.class); // Common when(annotation.useHeadersInDisplayName()).thenReturn(super.useHeadersInDisplayName); when(annotation.quoteCharacter()).thenReturn(super.quoteCharacter); when(annotation.delimiter()).thenReturn(super.delimiter); when(annotation.delimiterString()).thenReturn(super.delimiterString); when(annotation.emptyValue()).thenReturn(super.emptyValue); when(annotation.nullValues()).thenReturn(super.nullValues); when(annotation.maxCharsPerColumn()).thenReturn(super.maxCharsPerColumn); when(annotation.ignoreLeadingAndTrailingWhitespace()).thenReturn(super.ignoreLeadingAndTrailingWhitespace); // @CsvFileSource when(annotation.resources()).thenReturn(this.resources); when(annotation.files()).thenReturn(this.files); when(annotation.encoding()).thenReturn(this.encoding); when(annotation.lineSeparator()).thenReturn(this.lineSeparator); when(annotation.numLinesToSkip()).thenReturn(this.numLinesToSkip); return annotation; } } } ValueArgumentsProviderTests.java000066400000000000000000000132441455764576500370170ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.provider; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * @since 5.0 */ class ValueArgumentsProviderTests { @Test void multipleInputsAreNotAllowed() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new short[1], new byte[0], new int[1], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0])); assertThat(exception).hasMessageContaining( "Exactly one type of input must be provided in the @ValueSource annotation, but there were 2"); } @Test void onlyEmptyInputsAreNotAllowed() { var exception = assertThrows(PreconditionViolationException.class, () -> provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0])); assertThat(exception).hasMessageContaining( "Exactly one type of input must be provided in the @ValueSource annotation, but there were 0"); } /** * @since 5.1 */ @Test void providesShorts() { var arguments = provideArguments(new short[] { 23, 42 }, new byte[0], new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array((short) 23), array((short) 42)); } /** * @since 5.1 */ @Test void providesBytes() { var arguments = provideArguments(new short[0], new byte[] { 23, 42 }, new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array((byte) 23), array((byte) 42)); } @Test void providesInts() { var arguments = provideArguments(new short[0], new byte[0], new int[] { 23, 42 }, new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array(23), array(42)); } @Test void providesLongs() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[] { 23, 42 }, new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array(23L), array(42L)); } /** * @since 5.1 */ @Test void providesFloats() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[] { 23.32F, 42.24F }, new double[0], new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array(23.32F), array(42.24F)); } @Test void providesDoubles() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[] { 23.32, 42.24 }, new char[0], new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array(23.32), array(42.24)); } /** * @since 5.1 */ @Test void providesChars() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[0], new char[] { 'a', 'b', 'c' }, new boolean[0], new String[0], new Class[0]); assertThat(arguments).containsExactly(array('a'), array('b'), array('c')); } /** * @since 5.5 */ @Test void providesBooleans() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[] { true, false }, new String[0], new Class[0]); assertThat(arguments).containsExactly(array(true), array(false)); } @Test void providesStrings() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[] { "foo", "bar" }, new Class[0]); assertThat(arguments).containsExactly(array("foo"), array("bar")); } /** * @since 5.1 */ @Test void providesClasses() { var arguments = provideArguments(new short[0], new byte[0], new int[0], new long[0], new float[0], new double[0], new char[0], new boolean[0], new String[0], new Class[] { Integer.class, getClass() }); assertThat(arguments).containsExactly(array(Integer.class), array(getClass())); } private static Stream provideArguments(short[] shorts, byte[] bytes, int[] ints, long[] longs, float[] floats, double[] doubles, char[] chars, boolean[] booleans, String[] strings, Class[] classes) { var annotation = mock(ValueSource.class); when(annotation.shorts()).thenReturn(shorts); when(annotation.bytes()).thenReturn(bytes); when(annotation.ints()).thenReturn(ints); when(annotation.longs()).thenReturn(longs); when(annotation.floats()).thenReturn(floats); when(annotation.doubles()).thenReturn(doubles); when(annotation.chars()).thenReturn(chars); when(annotation.booleans()).thenReturn(booleans); when(annotation.strings()).thenReturn(strings); when(annotation.classes()).thenReturn(classes); var provider = new ValueArgumentsProvider(); provider.accept(annotation); return provider.provideArguments(mock()).map(Arguments::get); } private static Object[] array(Object... objects) { return objects; } } junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/000077500000000000000000000000001455764576500304115ustar00rootroot00000000000000AnnotationConsumerInitializerTests.java000066400000000000000000000120311455764576500402470ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.support; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.params.support.AnnotationConsumerInitializer.initialize; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.time.LocalDate; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.converter.AnnotationBasedArgumentConverter; import org.junit.jupiter.params.converter.JavaTimeConversionPattern; import org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; import org.junit.platform.commons.JUnitException; @DisplayName("AnnotationConsumerInitializer") class AnnotationConsumerInitializerTests { @Test @DisplayName("should initialize annotation consumer") void shouldInitializeAnnotationConsumer() throws NoSuchMethodException { var instance = new SomeAnnotationConsumer(); var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); assertThat(initialisedAnnotationConsumer.annotation) // .isInstanceOfSatisfying(CsvSource.class, // source -> assertThat(source.value()).containsExactly("a", "b")); } @Test @DisplayName("should initialize annotation-based ArgumentsProvider") void shouldInitializeAnnotationBasedArgumentsProvider() throws NoSuchMethodException { var instance = new SomeAnnotationBasedArgumentsProvider(); var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); initialisedAnnotationConsumer.provideArguments(mock()); assertThat(initialisedAnnotationConsumer.annotation) // .isInstanceOfSatisfying(CsvSource.class, // source -> assertThat(source.value()).containsExactly("a", "b")); } @Test @DisplayName("should initialize annotation-based ArgumentConverter") void shouldInitializeAnnotationBasedArgumentConverter() throws NoSuchMethodException { var instance = new SomeAnnotationBasedArgumentConverter(); var parameter = SubjectClass.class.getDeclaredMethod("bar", LocalDate.class).getParameters()[0]; var initialisedAnnotationConsumer = initialize(parameter, instance); ParameterContext parameterContext = mock(); when(parameterContext.getParameter()).thenReturn(parameter); initialisedAnnotationConsumer.convert("source", parameterContext); assertThat(initialisedAnnotationConsumer.annotation) // .isInstanceOfSatisfying(JavaTimeConversionPattern.class, // annotation -> assertThat(annotation.value()).isEqualTo("pattern")); } @Test @DisplayName("should throw exception when method is not annotated") void shouldThrowExceptionWhenMethodIsNotAnnotated() throws NoSuchMethodException { var instance = new SomeAnnotationConsumer(); var method = SubjectClass.class.getDeclaredMethod("noAnnotation", String.class); assertThatThrownBy(() -> initialize(method, instance)).isInstanceOf(JUnitException.class); } @Test @DisplayName("should throw exception when parameter is not annotated") void shouldThrowExceptionWhenParameterIsNotAnnotated() throws NoSuchMethodException { var instance = new SomeAnnotationConsumer(); var parameter = SubjectClass.class.getDeclaredMethod("noAnnotation", String.class).getParameters()[0]; assertThatThrownBy(() -> initialize(parameter, instance)).isInstanceOf(JUnitException.class); } private static class SomeAnnotationBasedArgumentsProvider extends AnnotationBasedArgumentsProvider { CsvSource annotation; @Override protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { this.annotation = annotation; return Stream.empty(); } } private static class SomeAnnotationBasedArgumentConverter extends AnnotationBasedArgumentConverter { JavaTimeConversionPattern annotation; @Override protected Object convert(Object source, Class targetType, JavaTimeConversionPattern annotation) { this.annotation = annotation; return null; } } private static class SomeAnnotationConsumer implements AnnotationConsumer { CsvSource annotation; @Override public void accept(CsvSource csvSource) { annotation = csvSource; } } @SuppressWarnings("unused") private static class SubjectClass { @CsvSource({ "a", "b" }) void foo() { } void bar(@JavaTimeConversionPattern("pattern") LocalDate date) { } void noAnnotation(String param) { } } } junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/000077500000000000000000000000001455764576500223675ustar00rootroot00000000000000ParameterizedTestNameFormatterIntegrationTests.kt000066400000000000000000000044341455764576500342250ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.TestInfo import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource class ParameterizedTestNameFormatterIntegrationTests { @ValueSource(strings = ["foo", "bar"]) @ParameterizedTest fun defaultDisplayName(param: String, info: TestInfo) { if (param.equals("foo")) { assertEquals("[1] foo", info.displayName) } else { assertEquals("[2] bar", info.displayName) } } @ValueSource(strings = ["foo", "bar"]) @ParameterizedTest(name = "{0}") fun `1st argument`(param: String, info: TestInfo) { if (param.equals("foo")) { assertEquals("foo", info.displayName) } else { assertEquals("bar", info.displayName) } } @ValueSource(strings = ["foo", "bar"]) @ParameterizedTest(name = "{displayName}") fun `it's an {enigma} '{0}'`(@Suppress("UNUSED_PARAMETER") param: String, info: TestInfo) { assertEquals("it's an {enigma} '{0}'(String, TestInfo)", info.displayName) } @ValueSource(strings = ["foo", "bar"]) @ParameterizedTest(name = "{displayName} - {0}") fun `displayName and 1st 'argument'`(param: String, info: TestInfo) { if (param.equals("foo")) { assertEquals("displayName and 1st 'argument'(String, TestInfo) - foo", info.displayName) } else { assertEquals("displayName and 1st 'argument'(String, TestInfo) - bar", info.displayName) } } @ValueSource(strings = ["foo", "bar"]) @ParameterizedTest(name = "{0} - {displayName}") fun `1st 'argument' and displayName`(param: String, info: TestInfo) { if (param.equals("foo")) { assertEquals("foo - 1st 'argument' and displayName(String, TestInfo)", info.displayName) } else { assertEquals("bar - 1st 'argument' and displayName(String, TestInfo)", info.displayName) } } } junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/000077500000000000000000000000001455764576500231565ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/000077500000000000000000000000001455764576500243075ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/jupiter/000077500000000000000000000000001455764576500257715ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/jupiter/params/000077500000000000000000000000001455764576500272545ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/jupiter/params/aggregator/000077500000000000000000000000001455764576500313765ustar00rootroot00000000000000ArgumentsAccessorKotlinTests.kt000066400000000000000000000046711455764576500375230ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.params.aggregator import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ParameterContext import org.junit.platform.commons.util.ReflectionUtils import org.mockito.Mockito.mock import org.mockito.Mockito.`when` import java.lang.reflect.Method /** * Unit tests for using [ArgumentsAccessor] from Kotlin. */ class ArgumentsAccessorKotlinTests { @Test fun `get() with reified type and index`() { assertEquals(1, defaultArgumentsAccessor(1, 1).get(0)) assertEquals('A', defaultArgumentsAccessor(1, 'A').get(0)) } @Test fun `get() with reified type and index for incompatible type`() { val exception = assertThrows { defaultArgumentsAccessor(1, Integer.valueOf(1)).get(0) } assertThat(exception).hasMessage( "Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [java.lang.Character]." ) } @Test fun `get() with index`() { assertEquals(1, defaultArgumentsAccessor(1, 1).get(0)) assertEquals('A', defaultArgumentsAccessor(1, 'A').get(0)) } @Test fun `get() with index and class reference`() { assertEquals(1, defaultArgumentsAccessor(1, 1).get(0, Integer::class.java)) assertEquals('A', defaultArgumentsAccessor(1, 'A').get(0, Character::class.java)) } fun defaultArgumentsAccessor(invocationIndex: Int, vararg arguments: Any): DefaultArgumentsAccessor { return DefaultArgumentsAccessor(parameterContext(), invocationIndex, *arguments) } fun parameterContext(): ParameterContext { val declaringExecutable: Method = ReflectionUtils.findMethod(DefaultArgumentsAccessorTests::class.java, "foo").get() val parameterContext: ParameterContext = mock() `when`(parameterContext.getDeclaringExecutable()).thenReturn(declaringExecutable) return parameterContext } fun foo() { } } DisplayNameTests.kt000066400000000000000000000020371455764576500351120ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/kotlin/org/junit/jupiter/params/aggregator/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ @file:Suppress("unused") package org.junit.jupiter.params.aggregator import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.TestInfo import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource // https://github.com/junit-team/junit5/issues/1836 object DisplayNameTests { @JvmStatic fun data() = arrayOf( arrayOf("A", 1), arrayOf("B", 2), arrayOf("C", 3), arrayOf("", 4), // empty is okay arrayOf(null, 5) // null was the problem ) @ParameterizedTest @MethodSource("data") fun test(char: String?, number: Int, info: TestInfo) { assertEquals("[$number] $char, $number", info.displayName) } } junit5-r5.10.2/junit-jupiter-params/src/test/resources/000077500000000000000000000000001455764576500231015ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/resources/broken.csv000066400000000000000000000023101455764576500250720ustar00rootroot00000000000000# more than 512 columns x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,junit5-r5.10.2/junit-jupiter-params/src/test/resources/default-max-chars.csv000066400000000000000000000100031455764576500271150ustar00rootroot00000000000000"41,6,8469,0,22,6336,9177,null,3,15,31,5734,6509,8770,9379,2,4,10,20,28,39,1490,5775,6410,6986,8493,8823,9298,9975,1,null,null,5,8,12,16,21,26,29,34,40,506,4491,5737,6034,6384,6434,6853,8178,8492,8503,8779,9106,9283,9339,9774,9982,null,null,null,null,7,9,11,13,null,17,null,null,23,27,null,30,32,35,null,null,176,837,3317,5715,5735,5743,5944,6310,6338,6398,6425,6436,6802,6917,7473,8397,8472,null,8494,8711,8776,8782,9009,9153,9210,9289,9336,9371,9400,9953,9980,9993,null,null,null,null,null,null,null,14,null,18,null,25,null,null,null,null,null,33,null,36,53,316,739,1409,3011,3924,4845,5730,null,5736,5741,5754,5807,5968,6056,6329,6337,6345,6387,6400,6420,6428,6435,6467,6575,6814,6911,6970,7111,7761,8283,8461,8470,8473,null,8496,8674,8722,8773,8778,8780,8803,8924,9078,9111,9172,9185,9270,9285,9296,9307,9337,9369,9376,9391,9633,9933,9967,9979,9981,9989,9994,null,null,null,19,24,null,null,null,null,37,46,140,199,505,669,814,1281,1430,1976,3096,3627,3934,4646,5455,5719,5733,null,null,5740,5742,5752,5758,5790,5828,5948,5974,6051,6278,6326,6331,null,null,6339,6365,6385,6388,6399,6405,6417,6424,6426,6433,null,null,6441,6492,6572,6739,6808,6845,6867,6915,6931,6985,7086,7463,7758,7797,8179,8349,8421,8467,null,8471,null,8476,8495,8497,8576,8708,8719,8761,8771,8774,8777,null,null,8781,8793,8806,8882,8937,9054,9084,9107,9134,9166,9175,9181,9187,9255,9282,9284,9287,9292,9297,9305,9319,null,9338,9342,9370,9375,9378,9380,9396,9546,9713,9798,9946,9956,9973,9978,null,null,null,9986,9991,null,9999,null,null,null,null,null,38,45,49,111,175,196,203,352,null,631,673,799,832,1056,1366,1415,1480,1819,2471,3016,3223,3532,3770,3931,4018,4592,4835,5233,5477,5718,5728,5732,null,5739,null,null,null,5745,5753,5756,5766,5785,5803,5823,5875,5946,5950,5971,5994,6043,6052,6124,6298,6317,6328,6330,6332,null,6341,6348,6369,null,6386,null,6396,null,null,6404,6408,6415,6419,6422,null,null,6427,6430,null,6440,6458,6471,6503,6520,6574,6721,6750,6807,6810,6843,6849,6863,6893,6912,6916,6919,6947,6983,null,6993,7088,7124,7466,7703,7759,7787,7962,null,8195,8331,8362,8411,8453,8462,8468,null,null,8474,8482,null,null,null,8500,8573,8619,8682,8710,8712,8721,8755,8767,null,8772,null,8775,null,null,null,null,8787,8795,8805,8819,8862,8886,8929,8978,9014,9076,9080,9087,null,9110,9112,9139,9163,9170,9173,9176,9178,9183,9186,9188,9240,9267,9278,null,null,null,9286,9288,9290,9293,null,null,9303,9306,9312,9326,null,null,9340,9366,null,null,9374,null,9377,null,null,9383,9393,9397,9493,9601,9652,9726,9789,9905,9942,9947,9954,9959,9969,9974,9976,null,9984,9988,9990,9992,9997,null,null,null,44,null,48,52,92,125,156,null,183,197,202,235,325,366,629,656,670,712,746,802,816,835,1026,1212,1293,1403,1414,1420,1471,1483,1604,1903,2432,2870,3014,3062,3219,3311,3336,3565,3730,3918,3927,3933,3975,4330,4546,4627,4709,4840,5158,5399,5456,5697,5716,null,5727,5729,5731,null,5738,null,5744,5746,null,null,5755,5757,5762,5774,5778,5786,5795,5805,5822,5824,5848,5895,5945,5947,5949,5961,5969,5973,5976,6014,6042,6049,null,6053,6117,6139,6290,6308,6314,6320,6327,null,null,null,null,6335,6340,6344,6346,6354,6366,6383,null,null,6390,6397,6401,null,6406,6409,6413,6416,6418,null,6421,6423,null,null,6429,6431,6438,null,6443,6462,6470,6472,6497,6506,6512,6528,6573,null,6648,6733,6748,6767,6805,null,6809,6813,6828,6844,6847,6852,6854,6864,6875,6910,null,6914,null,null,6918,6922,6944,6968,6976,6984,6991,7047,7087,7091,7112,7260,7464,7467,7656,7740,null,7760,7774,7795,7876,8110,8187,8202,8315,8341,8359,8391,8410,8414,8448,8455,null,8463,null,null,null,8475,8478,8483,8498,8502,8531,8575,8600,8624,8681,8688,8709,null,null,8716,8720,null,8735,8760,8766,8768,null,null,null,null,8784,8791,8794,8797,8804,null,8815,8820,8825,8867,8884,8887,8927,8936,8974,8986,9013,9041,9067,9077,9079,9081,9086,9093,9109,null,null,9119,9138,9144,9159,9164,9167,9171,null,9174,null,null,null,9179,9182,9184,null,null,null,9189,9223,9247,9258,9269,9275,9279,null,null,null,null,null,9291,null,9295,9301,9304,null,null,9310,9315,9324,9330,null,9341,9358,9367,9372,null,null,null,9382,9386,9392,9395,null,9398,9488,9509,9547,9616,9643,9702,94,122" junit5-r5.10.2/junit-jupiter-params/src/test/resources/exceeds-default-max-chars.csv000066400000000000000000000100041455764576500305340ustar00rootroot00000000000000"41,6,8469,0,22,6336,9177,null,3,15,31,5734,6509,8770,9379,2,4,10,20,28,39,1490,5775,6410,6986,8493,8823,9298,9975,1,null,null,5,8,12,16,21,26,29,34,40,506,4491,5737,6034,6384,6434,6853,8178,8492,8503,8779,9106,9283,9339,9774,9982,null,null,null,null,7,9,11,13,null,17,null,null,23,27,null,30,32,35,null,null,176,837,3317,5715,5735,5743,5944,6310,6338,6398,6425,6436,6802,6917,7473,8397,8472,null,8494,8711,8776,8782,9009,9153,9210,9289,9336,9371,9400,9953,9980,9993,null,null,null,null,null,null,null,14,null,18,null,25,null,null,null,null,null,33,null,36,53,316,739,1409,3011,3924,4845,5730,null,5736,5741,5754,5807,5968,6056,6329,6337,6345,6387,6400,6420,6428,6435,6467,6575,6814,6911,6970,7111,7761,8283,8461,8470,8473,null,8496,8674,8722,8773,8778,8780,8803,8924,9078,9111,9172,9185,9270,9285,9296,9307,9337,9369,9376,9391,9633,9933,9967,9979,9981,9989,9994,null,null,null,19,24,null,null,null,null,37,46,140,199,505,669,814,1281,1430,1976,3096,3627,3934,4646,5455,5719,5733,null,null,5740,5742,5752,5758,5790,5828,5948,5974,6051,6278,6326,6331,null,null,6339,6365,6385,6388,6399,6405,6417,6424,6426,6433,null,null,6441,6492,6572,6739,6808,6845,6867,6915,6931,6985,7086,7463,7758,7797,8179,8349,8421,8467,null,8471,null,8476,8495,8497,8576,8708,8719,8761,8771,8774,8777,null,null,8781,8793,8806,8882,8937,9054,9084,9107,9134,9166,9175,9181,9187,9255,9282,9284,9287,9292,9297,9305,9319,null,9338,9342,9370,9375,9378,9380,9396,9546,9713,9798,9946,9956,9973,9978,null,null,null,9986,9991,null,9999,null,null,null,null,null,38,45,49,111,175,196,203,352,null,631,673,799,832,1056,1366,1415,1480,1819,2471,3016,3223,3532,3770,3931,4018,4592,4835,5233,5477,5718,5728,5732,null,5739,null,null,null,5745,5753,5756,5766,5785,5803,5823,5875,5946,5950,5971,5994,6043,6052,6124,6298,6317,6328,6330,6332,null,6341,6348,6369,null,6386,null,6396,null,null,6404,6408,6415,6419,6422,null,null,6427,6430,null,6440,6458,6471,6503,6520,6574,6721,6750,6807,6810,6843,6849,6863,6893,6912,6916,6919,6947,6983,null,6993,7088,7124,7466,7703,7759,7787,7962,null,8195,8331,8362,8411,8453,8462,8468,null,null,8474,8482,null,null,null,8500,8573,8619,8682,8710,8712,8721,8755,8767,null,8772,null,8775,null,null,null,null,8787,8795,8805,8819,8862,8886,8929,8978,9014,9076,9080,9087,null,9110,9112,9139,9163,9170,9173,9176,9178,9183,9186,9188,9240,9267,9278,null,null,null,9286,9288,9290,9293,null,null,9303,9306,9312,9326,null,null,9340,9366,null,null,9374,null,9377,null,null,9383,9393,9397,9493,9601,9652,9726,9789,9905,9942,9947,9954,9959,9969,9974,9976,null,9984,9988,9990,9992,9997,null,null,null,44,null,48,52,92,125,156,null,183,197,202,235,325,366,629,656,670,712,746,802,816,835,1026,1212,1293,1403,1414,1420,1471,1483,1604,1903,2432,2870,3014,3062,3219,3311,3336,3565,3730,3918,3927,3933,3975,4330,4546,4627,4709,4840,5158,5399,5456,5697,5716,null,5727,5729,5731,null,5738,null,5744,5746,null,null,5755,5757,5762,5774,5778,5786,5795,5805,5822,5824,5848,5895,5945,5947,5949,5961,5969,5973,5976,6014,6042,6049,null,6053,6117,6139,6290,6308,6314,6320,6327,null,null,null,null,6335,6340,6344,6346,6354,6366,6383,null,null,6390,6397,6401,null,6406,6409,6413,6416,6418,null,6421,6423,null,null,6429,6431,6438,null,6443,6462,6470,6472,6497,6506,6512,6528,6573,null,6648,6733,6748,6767,6805,null,6809,6813,6828,6844,6847,6852,6854,6864,6875,6910,null,6914,null,null,6918,6922,6944,6968,6976,6984,6991,7047,7087,7091,7112,7260,7464,7467,7656,7740,null,7760,7774,7795,7876,8110,8187,8202,8315,8341,8359,8391,8410,8414,8448,8455,null,8463,null,null,null,8475,8478,8483,8498,8502,8531,8575,8600,8624,8681,8688,8709,null,null,8716,8720,null,8735,8760,8766,8768,null,null,null,null,8784,8791,8794,8797,8804,null,8815,8820,8825,8867,8884,8887,8927,8936,8974,8986,9013,9041,9067,9077,9079,9081,9086,9093,9109,null,null,9119,9138,9144,9159,9164,9167,9171,null,9174,null,null,null,9179,9182,9184,null,null,null,9189,9223,9247,9258,9269,9275,9279,null,null,null,null,null,9291,null,9295,9301,9304,null,null,9310,9315,9324,9330,null,9341,9358,9367,9372,null,null,null,9382,9386,9392,9395,null,9398,9488,9509,9547,9616,9643,9702,94,1223" junit5-r5.10.2/junit-jupiter-params/src/test/resources/leading-trailing-spaces.csv000066400000000000000000000000171455764576500303020ustar00rootroot00000000000000 ab , cd ef ,ghjunit5-r5.10.2/junit-jupiter-params/src/test/resources/log4j2-test.xml000066400000000000000000000006761455764576500257120ustar00rootroot00000000000000 junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/000077500000000000000000000000001455764576500236705ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/junit/000077500000000000000000000000001455764576500250215ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/junit/jupiter/000077500000000000000000000000001455764576500265035ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/junit/jupiter/params/000077500000000000000000000000001455764576500277665ustar00rootroot00000000000000two-column-with-headers.csv000066400000000000000000000005331455764576500351130ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/junit/jupiter/params#--------------------------------- FRUIT | RANK #--------------------------------- apple | 1 #--------------------------------- banana | 2 #--------------------------------- cherry | 3.14159265358979323846 #--------------------------------- | 0 #--------------------------------- NIL | 0 #--------------------------------- junit5-r5.10.2/junit-jupiter-params/src/test/resources/org/junit/jupiter/params/two-column.csv000066400000000000000000000000301455764576500326000ustar00rootroot00000000000000foo,1 bar,2 baz,3 qux,4 junit5-r5.10.2/junit-jupiter-params/src/test/resources/single-column.csv000066400000000000000000000000231455764576500263650ustar00rootroot00000000000000foo bar baz qux "" junit5-r5.10.2/junit-jupiter/000077500000000000000000000000001455764576500160405ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter/junit-jupiter.gradle.kts000066400000000000000000000005451455764576500226350ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Jupiter (Aggregator)" dependencies { api(platform(projects.junitBom)) api(projects.junitJupiterApi) api(projects.junitJupiterParams) runtimeOnly(projects.junitJupiterEngine) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-jupiter/src/000077500000000000000000000000001455764576500166275ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter/src/module/000077500000000000000000000000001455764576500201145ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter/src/module/org.junit.jupiter/000077500000000000000000000000001455764576500235145ustar00rootroot00000000000000junit5-r5.10.2/junit-jupiter/src/module/org.junit.jupiter/module-info.java000066400000000000000000000010441455764576500265740ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Aggregates all JUnit Jupiter modules. * * @since 5.4 */ module org.junit.jupiter { requires transitive org.junit.jupiter.api; requires transitive org.junit.jupiter.engine; requires transitive org.junit.jupiter.params; } junit5-r5.10.2/junit-platform-commons/000077500000000000000000000000001455764576500176535ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/junit-platform-commons.gradle.kts000066400000000000000000000016761455764576500262710ustar00rootroot00000000000000import junitbuild.java.ExecJarAction plugins { id("junitbuild.java-library-conventions") id("junitbuild.java-multi-release-sources") id("junitbuild.java-repackage-jars") `java-test-fixtures` } description = "JUnit Platform Commons" dependencies { api(platform(projects.junitBom)) compileOnlyApi(libs.apiguardian) } tasks.jar { val release9ClassesDir = sourceSets.mainRelease9.get().output.classesDirs.singleFile inputs.dir(release9ClassesDir).withPathSensitivity(PathSensitivity.RELATIVE) doLast(objects.newInstance(ExecJarAction::class).apply { javaLauncher = javaToolchains.launcherFor(java.toolchain) args.addAll( "--update", "--file", archiveFile.get().asFile.absolutePath, "--release", "9", "-C", release9ClassesDir.absolutePath, "." ) }) } tasks.codeCoverageClassesJar { exclude("org/junit/platform/commons/util/ModuleUtils.class") } eclipse { classpath { sourceSets -= project.sourceSets.mainRelease9.get() } } junit5-r5.10.2/junit-platform-commons/src/000077500000000000000000000000001455764576500204425ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/000077500000000000000000000000001455764576500213665ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/000077500000000000000000000000001455764576500223075ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/000077500000000000000000000000001455764576500230765ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/000077500000000000000000000000001455764576500242275ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500260535ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/000077500000000000000000000000001455764576500275265ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java000066400000000000000000000015151455764576500333030ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Base class for all {@link RuntimeException RuntimeExceptions} thrown * by JUnit. * * @since 1.0 */ @API(status = STABLE, since = "1.5") public class JUnitException extends RuntimeException { private static final long serialVersionUID = 1L; public JUnitException(String message) { super(message); } public JUnitException(String message, Throwable cause) { super(message, cause); } } PreconditionViolationException.java000066400000000000000000000016701455764576500365170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Thrown if a precondition is violated. * * @since 1.5 */ @API(status = STABLE, since = "1.5") @SuppressWarnings({ "deprecation", "exports" }) public class PreconditionViolationException extends org.junit.platform.commons.util.PreconditionViolationException { private static final long serialVersionUID = 1L; public PreconditionViolationException(String message) { super(message); } public PreconditionViolationException(String message, Throwable cause) { super(message, cause); } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/000077500000000000000000000000001455764576500317005ustar00rootroot00000000000000Testable.java000066400000000000000000000072211455764576500342310ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.annotation; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.apiguardian.api.API; /** * {@code @Testable} is used to signal to IDEs and tooling vendors that the * annotated or meta-annotated element is testable. * *

In this context, the term "testable" means that the annotated element * (typically a method, field, or class) can be executed by a {@code TestEngine} * as a test or test container on the JUnit Platform. * *

Motivation for {@code @Testable}

*

Some clients of the JUnit Platform, notably IDEs such as IntelliJ IDEA, * operate only on sources for test discovery. Thus, they cannot use the full * runtime discovery mechanism of the JUnit Platform since it relies on compiled * classes. {@code @Testable} therefore serves as an alternative mechanism for * IDEs to discover potential tests by analyzing the source code only. * *

Common Use Cases

*

{@code @Testable} will typically be used as a meta-annotation in order to * create a custom composed annotation that inherits the semantics * of {@code @Testable}. For example, the {@code @Test} and {@code @TestFactory} * annotations in JUnit Jupiter are meta-annotated with {@code @Testable}. *

For test programming models that do not rely on annotations, test classes, * test methods, or test fields may be directly annotated with {@code @Testable}. * Alternatively, if concrete test classes extend from a base class, the base class * can be annotated with {@code @Testable}. Note that {@code @Testable} is an * {@link Inherited @Inherited} annotation. * *

Requirements for IDEs and Tooling Vendors

*
    *
  • If a top-level class, static nested class, or inner class is not * annotated or meta-annotated with {@code @Testable} but contains a method or field * that is annotated or meta-annotated with {@code @Testable}, the class must * be considered to be a testable class.
  • *
  • If annotation hierarchies containing {@code @Testable} are present on * classes, methods, or fields in compiled byte code (e.g., in JARs in the user's * classpath), IDEs and tooling vendors must also take such annotation * hierarchies into consideration when performing annotation processing for * source code.
  • *
* *

Restrictions for TestEngine Implementations

*

A {@code TestEngine} must not in any way perform * discovery based on the presence of {@code @Testable}. In terms of * discovery, the presence of {@code @Testable} should only be meaningful to * clients such as IDEs and tooling vendors. A {@code TestEngine} implementation * is therefore required to discover tests based on information specific to * that test engine (e.g., annotations specific to that test engine). * *

Supported Target Elements

*

Since JUnit Platform version 1.7, {@code @Testable} may target any * declaration {@linkplain java.lang.annotation.ElementType element type}. This * includes the aforementioned method, field, and class elements. * * @since 1.0 */ @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @API(status = STABLE, since = "1.0") public @interface Testable { } package-info.java000066400000000000000000000001461455764576500350110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/** * Common annotations for the JUnit Platform. */ package org.junit.platform.commons.annotation; junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/function/000077500000000000000000000000001455764576500313535ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java000066400000000000000000000251621455764576500330020ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.function; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * A container object which may either contain a nullable value in case of * success or an exception in case of failure. * *

Instances of this class should be returned by methods instead of * {@link Optional} when callers might want to report the exception via logging * or by wrapping it in another exception at a later point in time, e.g. via * {@link #getOrThrow(Function)}. * *

Moreover, it makes it particularly convenient to attach follow-up actions * should the {@code Try} have been successful (cf. {@link #andThen} and * {@link #andThenTry}) or fallback actions should it not have been (cf. * {@link #orElse} and {@link #orElseTry}). * * @since 1.4 */ @API(status = MAINTAINED, since = "1.4") public abstract class Try { /** * Call the supplied {@link Callable} and return a successful {@code Try} * that contains the returned value or, in case an exception was thrown, a * failed {@code Try} that contains the exception. * * @param action the action to try; must not be {@code null} * @return a succeeded or failed {@code Try} depending on the outcome of the * supplied action; never {@code null} * @see #success(Object) * @see #failure(Exception) */ public static Try call(Callable action) { checkNotNull(action, "action"); return Try.of(() -> success(action.call())); } /** * Convert the supplied value into a succeeded {@code Try}. * * @param value the value to wrap; potentially {@code null} * @return a succeeded {@code Try} that contains the supplied value; never * {@code null} */ public static Try success(V value) { return new Success<>(value); } /** * Convert the supplied exception into a failed {@code Try}. * * @param cause the exception to wrap; must not be {@code null} * @return a failed {@code Try} that contains the supplied value; never * {@code null} */ public static Try failure(Exception cause) { return new Failure<>(checkNotNull(cause, "cause")); } // Cannot use Preconditions due to package cycle private static T checkNotNull(T input, String title) { if (input == null) { // Cannot use PreconditionViolationException due to package cycle throw new JUnitException(title + " must not be null"); } return input; } private static Try of(Callable> action) { try { return action.call(); } catch (Exception e) { return failure(e); } } private Try() { /* no-op */ } /** * If this {@code Try} is a success, apply the supplied transformer to its * value and return a new successful or failed {@code Try} depending on the * transformer's outcome; if this {@code Try} is a failure, do nothing. * * @param transformer the transformer to try; must not be {@code null} * @return a succeeded or failed {@code Try}; never {@code null} */ public abstract Try andThenTry(Transformer transformer); /** * If this {@code Try} is a success, apply the supplied function to its * value and return the resulting {@code Try}; if this {@code Try} is a * failure, do nothing. * * @param function the function to apply; must not be {@code null} * @return a succeeded or failed {@code Try}; never {@code null} */ public abstract Try andThen(Function> function); /** * If this {@code Try} is a failure, call the supplied action and return a * new successful or failed {@code Try} depending on the action's outcome; * if this {@code Try} is a success, do nothing. * * @param action the action to try; must not be {@code null} * @return a succeeded or failed {@code Try}; never {@code null} */ public abstract Try orElseTry(Callable action); /** * If this {@code Try} is a failure, call the supplied supplier and return * the resulting {@code Try}; if this {@code Try} is a success, do nothing. * * @param supplier the supplier to call; must not be {@code null} * @return a succeeded or failed {@code Try}; never {@code null} */ public abstract Try orElse(Supplier> supplier); /** * If this {@code Try} is a success, get the contained value; if this * {@code Try} is a failure, throw the contained exception. * * @return the contained value, if available; potentially {@code null} * @throws Exception if this {@code Try} is a failure */ public abstract V get() throws Exception; /** * If this {@code Try} is a success, get the contained value; if this * {@code Try} is a failure, call the supplied {@link Function} with the * contained exception and throw the resulting {@link Exception}. * * @param exceptionTransformer the transformer to be called with the * contained exception, if available; must not be {@code null} * @return the contained value, if available * @throws E if this {@code Try} is a failure */ public abstract V getOrThrow(Function exceptionTransformer) throws E; /** * If this {@code Try} is a success, call the supplied {@link Consumer} with * the contained value; otherwise, do nothing. * * @param valueConsumer the consumer to be called with the contained value, * if available; must not be {@code null} * @return the same {@code Try} for method chaining */ public abstract Try ifSuccess(Consumer valueConsumer); /** * If this {@code Try} is a failure, call the supplied {@link Consumer} with * the contained exception; otherwise, do nothing. * * @param causeConsumer the consumer to be called with the contained * exception, if available; must not be {@code null} * @return the same {@code Try} for method chaining */ public abstract Try ifFailure(Consumer causeConsumer); /** * If this {@code Try} is a failure, return an empty {@link Optional}; if * this {@code Try} is a success, wrap the contained value using * {@link Optional#ofNullable(Object)}. * * @return an {@link Optional}; never {@code null} but potentially * empty */ public abstract Optional toOptional(); /** * A transformer for values of type {@code S} to type {@code T}. * *

The {@code Transformer} interface is similar to {@link Function}, * except that a {@code Transformer} may throw an exception. */ @FunctionalInterface public interface Transformer { /** * Apply this transformer to the supplied value. * * @throws Exception if the transformation fails */ T apply(S value) throws Exception; } private static class Success extends Try { private final V value; Success(V value) { this.value = value; } @Override public Try andThenTry(Transformer transformer) { checkNotNull(transformer, "transformer"); return Try.call(() -> transformer.apply(this.value)); } @Override public Try andThen(Function> function) { checkNotNull(function, "function"); return Try.of(() -> function.apply(this.value)); } @Override public Try orElseTry(Callable action) { // don't call action because this Try is a success return this; } @Override public Try orElse(Supplier> supplier) { // don't call supplier because this Try is a success return this; } @Override public V get() { return this.value; } @Override public V getOrThrow(Function exceptionTransformer) { // don't call exceptionTransformer because this Try is a success return this.value; } @Override public Try ifSuccess(Consumer valueConsumer) { checkNotNull(valueConsumer, "valueConsumer"); valueConsumer.accept(this.value); return this; } @Override public Try ifFailure(Consumer causeConsumer) { // don't call causeConsumer because this Try was a success return this; } @Override public Optional toOptional() { return Optional.ofNullable(this.value); } @Override public boolean equals(Object that) { if (this == that) { return true; } if (that == null || this.getClass() != that.getClass()) { return false; } return Objects.equals(this.value, ((Success) that).value); } @Override public int hashCode() { return Objects.hash(value); } } private static class Failure extends Try { private final Exception cause; Failure(Exception cause) { this.cause = cause; } @Override public Try andThenTry(Transformer transformer) { // don't call transformer because this Try is a failure return uncheckedCast(); } @Override public Try andThen(Function> function) { // don't call function because this Try is a failure return uncheckedCast(); } @SuppressWarnings("unchecked") private Try uncheckedCast() { return (Try) this; } @Override public Try orElseTry(Callable action) { checkNotNull(action, "action"); return Try.call(action); } @Override public Try orElse(Supplier> supplier) { checkNotNull(supplier, "supplier"); return Try.of(supplier::get); } @Override public V get() throws Exception { throw this.cause; } @Override public V getOrThrow(Function exceptionTransformer) throws E { checkNotNull(exceptionTransformer, "exceptionTransformer"); throw exceptionTransformer.apply(this.cause); } @Override public Try ifSuccess(Consumer valueConsumer) { // don't call valueConsumer because this Try is a failure return this; } @Override public Try ifFailure(Consumer causeConsumer) { checkNotNull(causeConsumer, "causeConsumer"); causeConsumer.accept(this.cause); return this; } @Override public Optional toOptional() { return Optional.empty(); } @Override public boolean equals(Object that) { if (this == that) { return true; } if (that == null || this.getClass() != that.getClass()) { return false; } return Objects.equals(this.cause, ((Failure) that).cause); } @Override public int hashCode() { return Objects.hash(cause); } } } package-info.java000066400000000000000000000001571455764576500344660ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/function/** * Maintained functional interfaces and support classes. */ package org.junit.platform.commons.function; junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/000077500000000000000000000000001455764576500311545ustar00rootroot00000000000000LogRecordListener.java000066400000000000000000000120441455764576500353270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.logging; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * {@code LogRecordListener} is only intended for testing purposes within * JUnit's own test suite. * * @since 1.1 */ @API(status = INTERNAL, since = "1.1") public class LogRecordListener { // capture log records by thread to support parallel test execution private final ThreadLocal> logRecords = ThreadLocal.withInitial(ArrayList::new); /** * Inform the listener of a {@link LogRecord} that was submitted to JUL for * processing. */ public void logRecordSubmitted(LogRecord logRecord) { this.logRecords.get().add(logRecord); } /** * Get a stream of {@link LogRecord log records} that have been * {@linkplain #logRecordSubmitted submitted} to this listener by the * current thread. * *

As stated in the Javadoc for {@code LogRecord}, a submitted * {@code LogRecord} should not be updated by the client application. Thus, * the {@code LogRecords} in the returned stream should only be inspected for * testing purposes and not modified in any way. * * @see #stream(Level) * @see #stream(Class) * @see #stream(Class, Level) */ public Stream stream() { return this.logRecords.get().stream(); } /** * Get a stream of {@link LogRecord log records} that have been * {@linkplain #logRecordSubmitted submitted} to this listener by the current * thread at the given log level. * *

As stated in the Javadoc for {@code LogRecord}, a submitted * {@code LogRecord} should not be updated by the client application. Thus, * the {@code LogRecords} in the returned stream should only be inspected for * testing purposes and not modified in any way. * * @param level the log level for which to get the log records; never {@code null} * @since 1.4 * @see #stream() * @see #stream(Class) * @see #stream(Class, Level) */ public Stream stream(Level level) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. if (level == null) { throw new JUnitException("Level must not be null"); } return stream().filter(logRecord -> logRecord.getLevel() == level); } /** * Get a stream of {@link LogRecord log records} that have been * {@linkplain #logRecordSubmitted submitted} to this listener by the current * thread for the logger name equal to the name of the given class. * *

As stated in the Javadoc for {@code LogRecord}, a submitted * {@code LogRecord} should not be updated by the client application. Thus, * the {@code LogRecords} in the returned stream should only be inspected for * testing purposes and not modified in any way. * * @param clazz the class for which to get the log records; never {@code null} * @see #stream() * @see #stream(Level) * @see #stream(Class, Level) */ public Stream stream(Class clazz) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. if (clazz == null) { throw new JUnitException("Class must not be null"); } return stream().filter(logRecord -> logRecord.getLoggerName().equals(clazz.getName())); } /** * Get a stream of {@link LogRecord log records} that have been * {@linkplain #logRecordSubmitted submitted} to this listener by the current * thread for the logger name equal to the name of the given class at the given * log level. * *

As stated in the Javadoc for {@code LogRecord}, a submitted * {@code LogRecord} should not be updated by the client application. Thus, * the {@code LogRecords} in the returned stream should only be inspected for * testing purposes and not modified in any way. * * @param clazz the class for which to get the log records; never {@code null} * @param level the log level for which to get the log records; never {@code null} * @see #stream() * @see #stream(Level) * @see #stream(Class) */ public Stream stream(Class clazz, Level level) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. if (level == null) { throw new JUnitException("Level must not be null"); } return stream(clazz).filter(logRecord -> logRecord.getLevel() == level); } /** * Clear all existing {@link LogRecord log records} that have been * {@linkplain #logRecordSubmitted submitted} to this listener by the * current thread. */ public void clear() { this.logRecords.get().clear(); } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java000066400000000000000000000065511455764576500332450ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.logging; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.function.Supplier; import org.apiguardian.api.API; /** * The {@code Logger} API serves as a simple logging facade for * {@code java.util.logging} (JUL). * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public interface Logger { /** * Log the message from the provided {@code messageSupplier} at error level. * *

Maps to {@link java.util.logging.Level#SEVERE} in JUL. */ void error(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at error level. * *

Maps to {@link java.util.logging.Level#SEVERE} in JUL. */ void error(Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at warning level. * *

Maps to {@link java.util.logging.Level#WARNING} in JUL. */ void warn(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at warning level. * *

Maps to {@link java.util.logging.Level#WARNING} in JUL. */ void warn(Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at info level. * *

Maps to {@link java.util.logging.Level#INFO} in JUL. */ void info(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at info level. * *

Maps to {@link java.util.logging.Level#INFO} in JUL. */ void info(Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at config level. * *

Maps to {@link java.util.logging.Level#CONFIG} in JUL. */ void config(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at config level. * *

Maps to {@link java.util.logging.Level#CONFIG} in JUL. */ void config(Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at debug level. * *

Maps to {@link java.util.logging.Level#FINE} in JUL. */ void debug(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at debug level. * *

Maps to {@link java.util.logging.Level#FINE} in JUL. */ void debug(Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at trace level. * *

Maps to {@link java.util.logging.Level#FINER} in JUL. */ void trace(Supplier messageSupplier); /** * Log the provided {@code Throwable} and message from the provided * {@code messageSupplier} at trace level. * *

Maps to {@link java.util.logging.Level#FINER} in JUL. */ void trace(Throwable throwable, Supplier messageSupplier); } LoggerFactory.java000066400000000000000000000121171455764576500345110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.logging; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.LogRecord; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Factory for the {@link Logger} facade for JUL. * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class LoggerFactory { private LoggerFactory() { /* no-op */ } private static final Set listeners = ConcurrentHashMap.newKeySet(); /** * Get a {@link Logger} for the specified class. * * @param clazz the class for which to get the logger; never {@code null} * @return the logger */ public static Logger getLogger(Class clazz) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. if (clazz == null) { throw new JUnitException("Class must not be null"); } return new DelegatingLogger(clazz.getName()); } /** * Add the supplied {@link LogRecordListener} to the set of registered * listeners. */ public static void addListener(LogRecordListener listener) { listeners.add(listener); } /** * Remove the supplied {@link LogRecordListener} from the set of registered * listeners. */ public static void removeListener(LogRecordListener listener) { listeners.remove(listener); } private static final class DelegatingLogger implements Logger { private static final String FQCN = DelegatingLogger.class.getName(); private final String name; private final java.util.logging.Logger julLogger; DelegatingLogger(String name) { this.name = name; this.julLogger = java.util.logging.Logger.getLogger(this.name); } @Override public void error(Supplier messageSupplier) { log(Level.SEVERE, null, messageSupplier); } @Override public void error(Throwable throwable, Supplier messageSupplier) { log(Level.SEVERE, throwable, messageSupplier); } @Override public void warn(Supplier messageSupplier) { log(Level.WARNING, null, messageSupplier); } @Override public void warn(Throwable throwable, Supplier messageSupplier) { log(Level.WARNING, throwable, messageSupplier); } @Override public void info(Supplier messageSupplier) { log(Level.INFO, null, messageSupplier); } @Override public void info(Throwable throwable, Supplier messageSupplier) { log(Level.INFO, throwable, messageSupplier); } @Override public void config(Supplier messageSupplier) { log(Level.CONFIG, null, messageSupplier); } @Override public void config(Throwable throwable, Supplier messageSupplier) { log(Level.CONFIG, throwable, messageSupplier); } @Override public void debug(Supplier messageSupplier) { log(Level.FINE, null, messageSupplier); } @Override public void debug(Throwable throwable, Supplier messageSupplier) { log(Level.FINE, throwable, messageSupplier); } @Override public void trace(Supplier messageSupplier) { log(Level.FINER, null, messageSupplier); } @Override public void trace(Throwable throwable, Supplier messageSupplier) { log(Level.FINER, throwable, messageSupplier); } private void log(Level level, Throwable throwable, Supplier messageSupplier) { boolean loggable = this.julLogger.isLoggable(level); if (loggable || !listeners.isEmpty()) { LogRecord logRecord = createLogRecord(level, throwable, nullSafeGet(messageSupplier)); if (loggable) { this.julLogger.log(logRecord); } listeners.forEach(listener -> listener.logRecordSubmitted(logRecord)); } } private LogRecord createLogRecord(Level level, Throwable throwable, String message) { String sourceClassName = null; String sourceMethodName = null; boolean found = false; for (StackTraceElement element : new Throwable().getStackTrace()) { String className = element.getClassName(); if (FQCN.equals(className)) { found = true; } else if (found) { sourceClassName = className; sourceMethodName = element.getMethodName(); break; } } LogRecord logRecord = new LogRecord(level, message); logRecord.setLoggerName(this.name); logRecord.setThrown(throwable); logRecord.setSourceClassName(sourceClassName); logRecord.setSourceMethodName(sourceMethodName); logRecord.setResourceBundleName(this.julLogger.getResourceBundleName()); logRecord.setResourceBundle(this.julLogger.getResourceBundle()); return logRecord; } private static String nullSafeGet(Supplier messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } } } package-info.java000066400000000000000000000004521455764576500342650ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/** * Internal logging package. * *

DISCLAIMER

* *

These classes are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! */ package org.junit.platform.commons.logging; junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java000066400000000000000000000005341455764576500327170ustar00rootroot00000000000000/** * Common APIs and support utilities for the JUnit Platform. * *

DISCLAIMER

* *

Any API annotated with {@code @API(status = INTERNAL)} is intended solely * for usage within the JUnit framework itself. Any usage of internal * APIs by external parties is not supported! */ package org.junit.platform.commons; junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/000077500000000000000000000000001455764576500312425ustar00rootroot00000000000000AnnotationSupport.java000066400000000000000000000556121455764576500355460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code AnnotationSupport} provides static utility methods for common tasks * regarding annotations — for example, checking if a class, method, or * field is annotated with a particular annotation; finding annotations on a * given class, method, or field; finding fields or methods annotated with * a particular annotation, etc. * *

{@link org.junit.platform.engine.TestEngine TestEngine} and extension * authors are encouraged to use these supported methods in order to align with * the behavior of the JUnit Platform. * * @since 1.0 * @see ClassSupport * @see ModifierSupport * @see ReflectionSupport */ @API(status = MAINTAINED, since = "1.0") public final class AnnotationSupport { private AnnotationSupport() { /* no-op */ } /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the supplied optional * {@code element}. * * @param element an {@link Optional} containing the element on which to * search for the annotation; may be {@code null} or empty * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @since 1.3 * @see #isAnnotated(AnnotatedElement, Class) * @see #findAnnotation(Optional, Class) */ @API(status = MAINTAINED, since = "1.3") public static boolean isAnnotated(Optional element, Class annotationType) { return AnnotationUtils.isAnnotated(element, annotationType); } /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the supplied * {@code element}. * * @param element the element on which to search for the annotation; may be * {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @see #isAnnotated(Optional, Class) * @see #findAnnotation(AnnotatedElement, Class) */ public static boolean isAnnotated(AnnotatedElement element, Class annotationType) { return AnnotationUtils.isAnnotated(element, annotationType); } /** * Find the first annotation of {@code annotationType} that is either * present or meta-present on the supplied optional * {@code element}. * * @param the annotation type * @param element an {@link Optional} containing the element on which to * search for the annotation; may be {@code null} or empty * @param annotationType the annotation type to search for; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @since 1.1 * @see #findAnnotation(AnnotatedElement, Class) */ @API(status = MAINTAINED, since = "1.1") public static Optional findAnnotation(Optional element, Class annotationType) { return AnnotationUtils.findAnnotation(element, annotationType); } /** * Find the first annotation of {@code annotationType} that is either * directly present, meta-present, or indirectly * present on the supplied {@code element}. * *

If the element is a class and the annotation is neither directly * present nor meta-present on the class, this method will * additionally search on interfaces implemented by the class before * finding an annotation that is indirectly present on the class. * * @param the annotation type * @param element the element on which to search for the annotation; may be * {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty */ public static Optional findAnnotation(AnnotatedElement element, Class annotationType) { return AnnotationUtils.findAnnotation(element, annotationType); } /** * Find the first annotation of the specified type that is either * directly present, meta-present, or indirectly * present on the supplied class. * *

If the annotation is neither directly present nor meta-present * on the class, this method will additionally search on interfaces implemented * by the class before searching for an annotation that is indirectly present * on the class (i.e., within the class inheritance hierarchy). * *

If the annotation still has not been found, this method will optionally * search recursively through the enclosing class hierarchy if * {@link SearchOption#INCLUDE_ENCLOSING_CLASSES} is specified. * *

If {@link SearchOption#DEFAULT} is specified, this method has the same * semantics as {@link #findAnnotation(AnnotatedElement, Class)}. * * @param the annotation type * @param clazz the class on which to search for the annotation; may be {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param searchOption the {@code SearchOption} to use; never {@code null} * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @since 1.8 * @see SearchOption * @see #findAnnotation(AnnotatedElement, Class) */ @API(status = STABLE, since = "1.10") public static Optional findAnnotation(Class clazz, Class annotationType, SearchOption searchOption) { Preconditions.notNull(searchOption, "SearchOption must not be null"); return AnnotationUtils.findAnnotation(clazz, annotationType, searchOption == SearchOption.INCLUDE_ENCLOSING_CLASSES); } /** * Find all repeatable {@linkplain Annotation annotations} of the * supplied {@code annotationType} that are either present, * indirectly present, or meta-present on the supplied * optional {@code element}. * *

See {@link #findRepeatableAnnotations(AnnotatedElement, Class)} for * details of the algorithm used. * * @param the annotation type * @param element an {@link Optional} containing the element on which to * search for the annotation; may be {@code null} or empty * @param annotationType the repeatable annotation type to search for; never {@code null} * @return an immutable list of all such annotations found; never {@code null} * @since 1.5 * @see java.lang.annotation.Repeatable * @see java.lang.annotation.Inherited * @see #findRepeatableAnnotations(AnnotatedElement, Class) */ @API(status = MAINTAINED, since = "1.5") public static List findRepeatableAnnotations(Optional element, Class annotationType) { return AnnotationUtils.findRepeatableAnnotations(element, annotationType); } /** * Find all repeatable {@linkplain Annotation annotations} of the * supplied {@code annotationType} that are either present, * indirectly present, or meta-present on the supplied * {@link AnnotatedElement}. * *

This method extends the functionality of * {@link java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class)} * with additional support for meta-annotations. * *

In addition, if the element is a class and the repeatable annotation * is {@link java.lang.annotation.Inherited @Inherited}, this method will * search on superclasses first in order to support top-down semantics. * The result is that this algorithm finds repeatable annotations that * would be shadowed and therefore not visible according to Java's * standard semantics for inherited, repeatable annotations, but most * developers will naturally assume that all repeatable annotations in JUnit * are discovered regardless of whether they are declared stand-alone, in a * container, or as a meta-annotation (e.g., multiple declarations of * {@code @ExtendWith} within a test class hierarchy). * *

If the element is a class and the repeatable annotation is not * discovered within the class hierarchy, this method will additionally * search on interfaces implemented by each class in the hierarchy. * *

If the supplied {@code element} is {@code null}, this method returns * an empty list. * *

As of JUnit Platform 1.5, the search algorithm will also find * repeatable annotations used as meta-annotations on other repeatable * annotations. * * @param the annotation type * @param element the element to search on; may be {@code null} * @param annotationType the repeatable annotation type to search for; never {@code null} * @return an immutable list of all such annotations found; never {@code null} * @see java.lang.annotation.Repeatable * @see java.lang.annotation.Inherited */ public static List findRepeatableAnnotations(AnnotatedElement element, Class annotationType) { return AnnotationUtils.findRepeatableAnnotations(element, annotationType); } /** * Find all {@code public} {@linkplain Field fields} of the supplied class * or interface that are declared to be of the specified {@code fieldType} * and are annotated or meta-annotated with the specified * {@code annotationType}. * *

Consult the Javadoc for {@link Class#getFields()} for details on * inheritance and ordering. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param fieldType the declared type of fields to find; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return the list of all such fields found; neither {@code null} nor mutable * @see Class#getFields() * @see Field#getType() * @see #findAnnotatedFields(Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ public static List findPublicAnnotatedFields(Class clazz, Class fieldType, Class annotationType) { return AnnotationUtils.findPublicAnnotatedFields(clazz, fieldType, annotationType); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that are annotated or meta-annotated with the specified * {@code annotationType}, using top-down search semantics within the type * hierarchy. * *

Fields declared in the same class or interface will be ordered using * an algorithm that is deterministic but intentionally nonobvious. * *

The results will not contain fields that are hidden or * {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return the list of all such fields found; neither {@code null} nor mutable * @since 1.4 * @see Class#getDeclaredFields() * @see #findPublicAnnotatedFields(Class, Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFields(Class clazz, Class annotationType) { return findAnnotatedFields(clazz, annotationType, field -> true); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that are annotated or meta-annotated with the specified * {@code annotationType} and match the specified {@code predicate}, using * top-down search semantics within the type hierarchy. * *

Fields declared in the same class or interface will be ordered using * an algorithm that is deterministic but intentionally nonobvious. * *

The results will not contain fields that are hidden or * {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param predicate the field filter; never {@code null} * @return the list of all such fields found; neither {@code null} nor mutable * @since 1.10 * @see Class#getDeclaredFields() * @see #findPublicAnnotatedFields(Class, Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @API(status = MAINTAINED, since = "1.10") public static List findAnnotatedFields(Class clazz, Class annotationType, Predicate predicate) { return AnnotationUtils.findAnnotatedFields(clazz, annotationType, predicate); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that are annotated or meta-annotated with the specified * {@code annotationType} and match the specified {@code predicate}, using * the supplied hierarchy traversal mode. * *

Fields declared in the same class or interface will be ordered using * an algorithm that is deterministic but intentionally nonobvious. * *

The results will not contain fields that are hidden or * {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param predicate the field filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return the list of all such fields found; neither {@code null} nor mutable * @since 1.4 * @see Class#getDeclaredFields() * @see #findAnnotatedFields(Class, Class) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFields(Class clazz, Class annotationType, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return AnnotationUtils.findAnnotatedFields(clazz, annotationType, predicate, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } /** * Find the values of all non-static {@linkplain Field fields} of the supplied * {@code instance} that are annotated or meta-annotated with the * specified {@code annotationType}, using top-down search semantics within * the type hierarchy. * *

Values from fields declared in the same class or interface will be * ordered using an algorithm that is deterministic but intentionally * nonobvious. * *

The results will not contain values from fields that are hidden * or {@linkplain Field#isSynthetic() synthetic}. * * @param instance the instance in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return the list of all such field values found; neither {@code null} nor mutable * @since 1.4 * @see #findAnnotatedFields(Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFieldValues(Object instance, Class annotationType) { Preconditions.notNull(instance, "instance must not be null"); List fields = findAnnotatedFields(instance.getClass(), annotationType, ModifierSupport::isNotStatic, HierarchyTraversalMode.TOP_DOWN); return ReflectionUtils.readFieldValues(fields, instance); } /** * Find the values of all static {@linkplain Field fields} of the supplied * class or interface that are annotated or meta-annotated with the * specified {@code annotationType}, using top-down search semantics within * the type hierarchy. * *

Values from fields declared in the same class or interface will be * ordered using an algorithm that is deterministic but intentionally * nonobvious. * *

The results will not contain values from fields that are hidden * or {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return the list of all such field values found; neither {@code null} nor mutable * @since 1.4 * @see #findAnnotatedFields(Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFieldValues(Class clazz, Class annotationType) { List fields = findAnnotatedFields(clazz, annotationType, ModifierSupport::isStatic, HierarchyTraversalMode.TOP_DOWN); return ReflectionUtils.readFieldValues(fields, null); } /** * Find the values of all non-static {@linkplain Field fields} of the supplied * {@code instance} that are declared to be of the specified {@code fieldType} * and are annotated or meta-annotated with the specified * {@code annotationType}, using top-down search semantics within the type * hierarchy. * *

Values from fields declared in the same class or interface will be * ordered using an algorithm that is deterministic but intentionally * nonobvious. * *

The results will not contain values from fields that are hidden * or {@linkplain Field#isSynthetic() synthetic}. * * @param instance the instance in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param fieldType the declared type of fields to find; never {@code null} * @return the list of all such field values found; neither {@code null} nor mutable * @since 1.4 * @see Field#getType() * @see #findAnnotatedFields(Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @SuppressWarnings("unchecked") @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFieldValues(Object instance, Class annotationType, Class fieldType) { Preconditions.notNull(instance, "instance must not be null"); Preconditions.notNull(fieldType, "fieldType must not be null"); Predicate predicate = // field -> ModifierSupport.isNotStatic(field) && fieldType.isAssignableFrom(field.getType()); List fields = findAnnotatedFields(instance.getClass(), annotationType, predicate, HierarchyTraversalMode.TOP_DOWN); return (List) ReflectionUtils.readFieldValues(fields, instance); } /** * Find the values of all static {@linkplain Field fields} of the supplied * class or interface that are declared to be of the specified * {@code fieldType} and are annotated or meta-annotated with the * specified {@code annotationType}, using top-down search semantics within * the type hierarchy. * *

Values from fields declared in the same class or interface will be * ordered using an algorithm that is deterministic but intentionally * nonobvious. * *

The results will not contain values from fields that are hidden * or {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param fieldType the declared type of fields to find; never {@code null} * @return the list of all such field values found; neither {@code null} nor mutable * @since 1.4 * @see Field#getType() * @see #findAnnotatedFields(Class, Class) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#findFields(Class, Predicate, HierarchyTraversalMode) * @see ReflectionSupport#tryToReadFieldValue(Field, Object) */ @SuppressWarnings("unchecked") @API(status = MAINTAINED, since = "1.4") public static List findAnnotatedFieldValues(Class clazz, Class annotationType, Class fieldType) { Preconditions.notNull(fieldType, "fieldType must not be null"); Predicate predicate = // field -> ModifierSupport.isStatic(field) && fieldType.isAssignableFrom(field.getType()); List fields = findAnnotatedFields(clazz, annotationType, predicate, HierarchyTraversalMode.TOP_DOWN); return (List) ReflectionUtils.readFieldValues(fields, null); } /** * Find all {@linkplain Method methods} of the supplied class or interface * that are annotated or meta-annotated with the specified * {@code annotationType}. * * @param clazz the class or interface in which to find the methods; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return the list of all such methods found; neither {@code null} nor mutable */ public static List findAnnotatedMethods(Class clazz, Class annotationType, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return AnnotationUtils.findAnnotatedMethods(clazz, annotationType, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } } ClassSupport.java000066400000000000000000000046421455764576500344760ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.util.ClassUtils; /** * {@code ClassSupport} provides static utility methods for common tasks * regarding {@linkplain Class classes} — for example, generating a * comma-separated list of fully qualified class names for a set of supplied * classes. * *

{@link org.junit.platform.engine.TestEngine TestEngine} and extension * authors are encouraged to use these supported methods in order to align with * the behavior of the JUnit Platform. * * @since 1.1 * @see AnnotationSupport * @see ModifierSupport * @see ReflectionSupport */ @API(status = MAINTAINED, since = "1.1") public final class ClassSupport { private ClassSupport() { /* no-op */ } /** * Generate a comma-separated list of fully qualified class names for the * supplied classes. * * @param classes the classes whose names should be included in the * generated string * @return a comma-separated list of fully qualified class names, or an empty * string if the supplied class array is {@code null} or empty * @see #nullSafeToString(Function, Class...) */ public static String nullSafeToString(Class... classes) { return ClassUtils.nullSafeToString(classes); } /** * Generate a comma-separated list of mapped values for the supplied classes. * *

The values are generated by the supplied {@code mapper} * (e.g., {@code Class::getName}, {@code Class::getSimpleName}, etc.), unless * a class reference is {@code null} in which case it will be mapped to * {@code "null"}. * * @param mapper the mapper to use; never {@code null} * @param classes the classes to map * @return a comma-separated list of mapped values, or an empty string if * the supplied class array is {@code null} or empty * @see #nullSafeToString(Class...) */ public static String nullSafeToString(Function, ? extends String> mapper, Class... classes) { return ClassUtils.nullSafeToString(mapper, classes); } } HierarchyTraversalMode.java000066400000000000000000000015601455764576500364370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; /** * Modes in which a hierarchy can be traversed — for example, when * searching for methods or fields within a class hierarchy. * * @since 1.0 * @see #TOP_DOWN * @see #BOTTOM_UP */ @API(status = MAINTAINED, since = "1.0") public enum HierarchyTraversalMode { /** * Traverse the hierarchy using top-down semantics. */ TOP_DOWN, /** * Traverse the hierarchy using bottom-up semantics. */ BOTTOM_UP; } ModifierSupport.java000066400000000000000000000165611455764576500351720ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Member; import org.apiguardian.api.API; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code ModifierSupport} provides static utility methods for working with * class and member {@linkplain java.lang.reflect.Modifier modifiers} — * for example, to determine if a class or member is declared as * {@code public}, {@code private}, {@code abstract}, {@code static}, etc. * *

{@link org.junit.platform.engine.TestEngine TestEngine} and extension * authors are encouraged to use these supported methods in order to align with * the behavior of the JUnit Platform. * * @since 1.4 * @see java.lang.reflect.Modifier * @see AnnotationSupport * @see ClassSupport * @see ReflectionSupport */ @API(status = MAINTAINED, since = "1.4") public final class ModifierSupport { private ModifierSupport() { /* no-op */ } /** * Determine if the supplied class is {@code public}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is {@code public} * @see java.lang.reflect.Modifier#isPublic(int) */ public static boolean isPublic(Class clazz) { return ReflectionUtils.isPublic(clazz); } /** * Determine if the supplied member is {@code public}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is {@code public} * @see java.lang.reflect.Modifier#isPublic(int) */ public static boolean isPublic(Member member) { return ReflectionUtils.isPublic(member); } /** * Determine if the supplied class is {@code private}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is {@code private} * @see java.lang.reflect.Modifier#isPrivate(int) */ public static boolean isPrivate(Class clazz) { return ReflectionUtils.isPrivate(clazz); } /** * Determine if the supplied member is {@code private}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is {@code private} * @see java.lang.reflect.Modifier#isPrivate(int) */ public static boolean isPrivate(Member member) { return ReflectionUtils.isPrivate(member); } /** * Determine if the supplied class is not {@code private}. * *

In other words this method will return {@code true} for classes * declared as {@code public}, {@code protected}, or * package private and {@code false} for classes declared as * {@code private}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is not {@code private} * @see java.lang.reflect.Modifier#isPublic(int) * @see java.lang.reflect.Modifier#isProtected(int) * @see java.lang.reflect.Modifier#isPrivate(int) */ public static boolean isNotPrivate(Class clazz) { return ReflectionUtils.isNotPrivate(clazz); } /** * Determine if the supplied member is not {@code private}. * *

In other words this method will return {@code true} for members * declared as {@code public}, {@code protected}, or * package private and {@code false} for members declared as * {@code private}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is not {@code private} * @see java.lang.reflect.Modifier#isPublic(int) * @see java.lang.reflect.Modifier#isProtected(int) * @see java.lang.reflect.Modifier#isPrivate(int) */ public static boolean isNotPrivate(Member member) { return ReflectionUtils.isNotPrivate(member); } /** * Determine if the supplied class is {@code abstract}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is {@code abstract} * @see java.lang.reflect.Modifier#isAbstract(int) */ public static boolean isAbstract(Class clazz) { return ReflectionUtils.isAbstract(clazz); } /** * Determine if the supplied member is {@code abstract}. * * @param member the class to check; never {@code null} * @return {@code true} if the member is {@code abstract} * @see java.lang.reflect.Modifier#isAbstract(int) */ public static boolean isAbstract(Member member) { return ReflectionUtils.isAbstract(member); } /** * Determine if the supplied class is {@code static}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is {@code static} * @see java.lang.reflect.Modifier#isStatic(int) */ public static boolean isStatic(Class clazz) { return ReflectionUtils.isStatic(clazz); } /** * Determine if the supplied member is {@code static}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is {@code static} * @see java.lang.reflect.Modifier#isStatic(int) */ public static boolean isStatic(Member member) { return ReflectionUtils.isStatic(member); } /** * Determine if the supplied class is not {@code static}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is not {@code static} * @see java.lang.reflect.Modifier#isStatic(int) */ public static boolean isNotStatic(Class clazz) { return ReflectionUtils.isNotStatic(clazz); } /** * Determine if the supplied member is not {@code static}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is not {@code static} * @see java.lang.reflect.Modifier#isStatic(int) */ public static boolean isNotStatic(Member member) { return ReflectionUtils.isNotStatic(member); } /** * Determine if the supplied class is {@code final}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is {@code final} * @since 1.5 * @see java.lang.reflect.Modifier#isFinal(int) */ @API(status = MAINTAINED, since = "1.5") public static boolean isFinal(Class clazz) { return ReflectionUtils.isFinal(clazz); } /** * Determine if the supplied class is not {@code final}. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is not {@code final} * @since 1.5 * @see java.lang.reflect.Modifier#isFinal(int) */ @API(status = MAINTAINED, since = "1.5") public static boolean isNotFinal(Class clazz) { return ReflectionUtils.isNotFinal(clazz); } /** * Determine if the supplied member is {@code final}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is {@code final} * @since 1.5 * @see java.lang.reflect.Modifier#isFinal(int) */ @API(status = MAINTAINED, since = "1.5") public static boolean isFinal(Member member) { return ReflectionUtils.isFinal(member); } /** * Determine if the supplied member is not {@code final}. * * @param member the member to check; never {@code null} * @return {@code true} if the member is not {@code final} * @since 1.5 * @see java.lang.reflect.Modifier#isFinal(int) */ @API(status = MAINTAINED, since = "1.5") public static boolean isNotFinal(Member member) { return ReflectionUtils.isNotFinal(member); } } ReflectionSupport.java000066400000000000000000000532741455764576500355300ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URI; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; /** * {@code ReflectionSupport} provides static utility methods for common * reflection tasks — for example, scanning for classes in the class-path * or module-path, loading classes, finding methods, invoking methods, etc. * *

{@link org.junit.platform.engine.TestEngine TestEngine} and extension * authors are encouraged to use these supported methods in order to align with * the behavior of the JUnit Platform. * * @since 1.0 * @see AnnotationSupport * @see ClassSupport * @see ModifierSupport */ @API(status = MAINTAINED, since = "1.0") public final class ReflectionSupport { private ReflectionSupport() { /* no-op */ } /** * Load a class by its primitive name or fully qualified name, * using the default {@link ClassLoader}. * *

Class names for arrays may be specified using either the JVM's internal * String representation (e.g., {@code [[I} for {@code int[][]}, * {@code [Ljava.lang.String;} for {@code java.lang.String[]}, etc.) or * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, * etc.). * * @param name the name of the class to load; never {@code null} or blank * @return an {@code Optional} containing the loaded class; never {@code null} * but potentially empty if no such class could be loaded * @deprecated Please use {@link #tryToLoadClass(String)} instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated @SuppressWarnings("deprecation") public static Optional> loadClass(String name) { return ReflectionUtils.loadClass(name); } /** * Try to load a class by its primitive name or fully qualified * name, using the default {@link ClassLoader}. * *

Class names for arrays may be specified using either the JVM's internal * String representation (e.g., {@code [[I} for {@code int[][]}, * {@code [Lava.lang.String;} for {@code java.lang.String[]}, etc.) or * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, * etc.). * * @param name the name of the class to load; never {@code null} or blank * @return a successful {@code Try} containing the loaded class or a failed * {@code Try} containing the exception if no such class could be loaded; * never {@code null} * @since 1.4 * @see #tryToLoadClass(String, ClassLoader) */ @API(status = MAINTAINED, since = "1.4") public static Try> tryToLoadClass(String name) { return ReflectionUtils.tryToLoadClass(name); } /** * Try to load a class by its primitive name or fully qualified * name, using the supplied {@link ClassLoader}. * *

See {@link ReflectionSupport#tryToLoadClass(String) tryToLoadClass(String)} * for details on support for class names for arrays. * * @param name the name of the class to load; never {@code null} or blank * @param classLoader the {@code ClassLoader} to use; never {@code null} * @return a successful {@code Try} containing the loaded class or a failed * {@code Try} containing the exception if no such class could be loaded; * never {@code null} * @since 1.10 * @see #tryToLoadClass(String) */ @API(status = EXPERIMENTAL, since = "1.10") public static Try> tryToLoadClass(String name, ClassLoader classLoader) { return ReflectionUtils.tryToLoadClass(name, classLoader); } /** * Find all {@linkplain Class classes} in the supplied classpath {@code root} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The classpath scanning algorithm searches recursively in subpackages * beginning with the root of the classpath. * * @param root the URI for the classpath root in which to scan; never * {@code null} * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty * @see #findAllClassesInPackage(String, Predicate, Predicate) * @see #findAllClassesInModule(String, Predicate, Predicate) */ public static List> findAllClassesInClasspathRoot(URI root, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.findAllClassesInClasspathRoot(root, classFilter, classNameFilter); } /** * Find all {@linkplain Class classes} in the supplied classpath {@code root} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The classpath scanning algorithm searches recursively in subpackages * beginning with the root of the classpath. * * @param root the URI for the classpath root in which to scan; never * {@code null} * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return a stream of all such classes found; never {@code null} * but potentially empty * @since 1.10 * @see #streamAllClassesInPackage(String, Predicate, Predicate) * @see #streamAllClassesInModule(String, Predicate, Predicate) */ @API(status = MAINTAINED, since = "1.10") public static Stream> streamAllClassesInClasspathRoot(URI root, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.streamAllClassesInClasspathRoot(root, classFilter, classNameFilter); } /** * Find all {@linkplain Class classes} in the supplied {@code basePackageName} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The classpath scanning algorithm searches recursively in subpackages * beginning within the supplied base package. * * @param basePackageName the name of the base package in which to start * scanning; must not be {@code null} and must be valid in terms of Java * syntax * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty * @see #findAllClassesInClasspathRoot(URI, Predicate, Predicate) * @see #findAllClassesInModule(String, Predicate, Predicate) */ public static List> findAllClassesInPackage(String basePackageName, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.findAllClassesInPackage(basePackageName, classFilter, classNameFilter); } /** * Find all {@linkplain Class classes} in the supplied {@code basePackageName} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The classpath scanning algorithm searches recursively in subpackages * beginning within the supplied base package. * * @param basePackageName the name of the base package in which to start * scanning; must not be {@code null} and must be valid in terms of Java * syntax * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return a stream of all such classes found; never {@code null} * but potentially empty * @since 1.10 * @see #streamAllClassesInClasspathRoot(URI, Predicate, Predicate) * @see #streamAllClassesInModule(String, Predicate, Predicate) */ @API(status = MAINTAINED, since = "1.10") public static Stream> streamAllClassesInPackage(String basePackageName, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.streamAllClassesInPackage(basePackageName, classFilter, classNameFilter); } /** * Find all {@linkplain Class classes} in the supplied {@code moduleName} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The module-path scanning algorithm searches recursively in all * packages contained in the module. * * @param moduleName the name of the module to scan; never {@code null} or * empty * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty * @since 1.1.1 * @see #findAllClassesInClasspathRoot(URI, Predicate, Predicate) * @see #findAllClassesInPackage(String, Predicate, Predicate) */ public static List> findAllClassesInModule(String moduleName, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.findAllClassesInModule(moduleName, classFilter, classNameFilter); } /** * Find all {@linkplain Class classes} in the supplied {@code moduleName} * that match the specified {@code classFilter} and {@code classNameFilter} * predicates. * *

The module-path scanning algorithm searches recursively in all * packages contained in the module. * * @param moduleName the name of the module to scan; never {@code null} or * empty * @param classFilter the class type filter; never {@code null} * @param classNameFilter the class name filter; never {@code null} * @return a stream of all such classes found; never {@code null} * but potentially empty * @since 1.10 * @see #streamAllClassesInClasspathRoot(URI, Predicate, Predicate) * @see #streamAllClassesInPackage(String, Predicate, Predicate) */ @API(status = MAINTAINED, since = "1.10") public static Stream> streamAllClassesInModule(String moduleName, Predicate> classFilter, Predicate classNameFilter) { return ReflectionUtils.streamAllClassesInModule(moduleName, classFilter, classNameFilter); } /** * Create a new instance of the specified {@link Class} by invoking * the constructor whose argument list matches the types of the supplied * arguments. * *

The constructor will be made accessible if necessary, and any checked * exception will be {@linkplain ExceptionUtils#throwAsUncheckedException masked} * as an unchecked exception. * * @param clazz the class to instantiate; never {@code null} * @param args the arguments to pass to the constructor, none of which may * be {@code null} * @return the new instance; never {@code null} * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ public static T newInstance(Class clazz, Object... args) { return ReflectionUtils.newInstance(clazz, args); } /** * Invoke the supplied method, making it accessible if necessary and * {@linkplain ExceptionUtils#throwAsUncheckedException masking} any * checked exception as an unchecked exception. * * @param method the method to invoke; never {@code null} * @param target the object on which to invoke the method; may be * {@code null} if the method is {@code static} * @param args the arguments to pass to the method * @return the value returned by the method invocation or {@code null} * if the return type is {@code void} * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ public static Object invokeMethod(Method method, Object target, Object... args) { return ReflectionUtils.invokeMethod(method, target, args); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that match the specified {@code predicate}. * *

Fields declared in the same class or interface will be ordered using * an algorithm that is deterministic but intentionally nonobvious. * *

The results will not contain fields that are hidden or * {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param predicate the field filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return an immutable list of all such fields found; never {@code null} * but potentially empty * @since 1.4 */ @API(status = MAINTAINED, since = "1.4") public static List findFields(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return ReflectionUtils.findFields(clazz, predicate, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that match the specified {@code predicate}. * *

Fields declared in the same class or interface will be ordered using * an algorithm that is deterministic but intentionally nonobvious. * *

The results will not contain fields that are hidden or * {@linkplain Field#isSynthetic() synthetic}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param predicate the field filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return a stream of all such fields found; never {@code null} * but potentially empty * @since 1.10 */ @API(status = MAINTAINED, since = "1.10") public static Stream streamFields(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return ReflectionUtils.streamFields(clazz, predicate, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } /** * Try to read the value of a potentially inaccessible field. * *

If an exception occurs while reading the field, a failed {@link Try} * is returned that contains the corresponding exception. * * @param field the field to read; never {@code null} * @param instance the instance from which the value is to be read; may * be {@code null} for a static field * @since 1.4 */ @API(status = MAINTAINED, since = "1.4") public static Try tryToReadFieldValue(Field field, Object instance) { return ReflectionUtils.tryToReadFieldValue(field, instance); } /** * Find the first {@link Method} of the supplied class or interface that * meets the specified criteria, beginning with the specified class or * interface and traversing up the type hierarchy until such a method is * found or the type hierarchy is exhausted. * *

As of JUnit Platform 1.10, this method uses the {@link ClassLoader} of * the supplied {@code clazz} to load parameter types instead of using the * default {@code ClassLoader}, which allows parameter types to be * resolved in different {@code ClassLoader} arrangements. * *

The algorithm does not search for methods in {@link java.lang.Object}. * * @param clazz the class or interface in which to find the method; never {@code null} * @param methodName the name of the method to find; never {@code null} or empty * @param parameterTypeNames the fully qualified names of the types of parameters * accepted by the method, if any, provided as a comma-separated list * @return an {@code Optional} containing the method found; never {@code null} * but potentially empty if no such method could be found * @see #findMethod(Class, String, Class...) */ public static Optional findMethod(Class clazz, String methodName, String parameterTypeNames) { return ReflectionUtils.findMethod(clazz, methodName, parameterTypeNames); } /** * Find the first {@link Method} of the supplied class or interface that * meets the specified criteria, beginning with the specified class or * interface and traversing up the type hierarchy until such a method is * found or the type hierarchy is exhausted. * *

The algorithm does not search for methods in {@link java.lang.Object}. * * @param clazz the class or interface in which to find the method; never {@code null} * @param methodName the name of the method to find; never {@code null} or empty * @param parameterTypes the types of parameters accepted by the method, if any; * never {@code null} * @return an {@code Optional} containing the method found; never {@code null} * but potentially empty if no such method could be found * @see #findMethod(Class, String, String) */ public static Optional findMethod(Class clazz, String methodName, Class... parameterTypes) { return ReflectionUtils.findMethod(clazz, methodName, parameterTypes); } /** * Find all distinct {@linkplain Method methods} of the supplied class or * interface that match the specified {@code predicate}. * *

The results will not contain instance methods that are overridden * or {@code static} methods that are hidden. * *

If you are looking for methods annotated with a certain annotation * type, consider using * {@link AnnotationSupport#findAnnotatedMethods(Class, Class, HierarchyTraversalMode)}. * * @param clazz the class or interface in which to find the methods; never {@code null} * @param predicate the method filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return an immutable list of all such methods found; never {@code null} * but potentially empty */ public static List findMethods(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return ReflectionUtils.findMethods(clazz, predicate, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } /** * Find all distinct {@linkplain Method methods} of the supplied class or * interface that match the specified {@code predicate}. * *

The results will not contain instance methods that are overridden * or {@code static} methods that are hidden. * *

If you are looking for methods annotated with a certain annotation * type, consider using * {@link AnnotationSupport#findAnnotatedMethods(Class, Class, HierarchyTraversalMode)}. * * @param clazz the class or interface in which to find the methods; never {@code null} * @param predicate the method filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return a stream of all such methods found; never {@code null} * but potentially empty * @since 1.10 */ @API(status = MAINTAINED, since = "1.10") public static Stream streamMethods(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return ReflectionUtils.streamMethods(clazz, predicate, ReflectionUtils.HierarchyTraversalMode.valueOf(traversalMode.name())); } /** * Find all nested classes within the supplied class, or inherited by the * supplied class, that conform to the supplied predicate. * *

This method does not search for nested classes * recursively. * *

As of JUnit Platform 1.6, this method detects cycles in inner * class hierarchies — from the supplied class up to the outermost * enclosing class — and throws a {@link JUnitException} if such a cycle * is detected. Cycles within inner class hierarchies below the * supplied class are not detected by this method. * * @param clazz the class to be searched; never {@code null} * @param predicate the predicate against which the list of nested classes is * checked; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty * @throws JUnitException if a cycle is detected within an inner class hierarchy */ public static List> findNestedClasses(Class clazz, Predicate> predicate) throws JUnitException { return ReflectionUtils.findNestedClasses(clazz, predicate); } /** * Find all nested classes within the supplied class, or inherited by the * supplied class, that conform to the supplied predicate. * *

This method does not search for nested classes * recursively. * *

As of JUnit Platform 1.6, this method detects cycles in inner * class hierarchies — from the supplied class up to the outermost * enclosing class — and throws a {@link JUnitException} if such a cycle * is detected. Cycles within inner class hierarchies below the * supplied class are not detected by this method. * * @param clazz the class to be searched; never {@code null} * @param predicate the predicate against which the list of nested classes is * checked; never {@code null} * @return a stream of all such classes found; never {@code null} * but potentially empty * @throws JUnitException if a cycle is detected within an inner class hierarchy * @since 1.10 */ @API(status = MAINTAINED, since = "1.10") public static Stream> streamNestedClasses(Class clazz, Predicate> predicate) throws JUnitException { return ReflectionUtils.streamNestedClasses(clazz, predicate); } } SearchOption.java000066400000000000000000000022271455764576500344270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Search options for finding an annotation within a class hierarchy. * * @since 1.8 * @see #DEFAULT * @see #INCLUDE_ENCLOSING_CLASSES */ @API(status = STABLE, since = "1.10") public enum SearchOption { /** * Search the inheritance hierarchy (i.e., the current class, implemented * interfaces, and superclasses), but do not search on enclosing classes. * * @see Class#getSuperclass() * @see Class#getInterfaces() */ DEFAULT, /** * Search the inheritance hierarchy as with the {@link #DEFAULT} search option * but also search the {@linkplain Class#getEnclosingClass() enclosing class} * hierarchy for inner classes (i.e., a non-static member classes). */ INCLUDE_ENCLOSING_CLASSES; } package-info.java000066400000000000000000000007701455764576500343560ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/support/** * Maintained common support APIs provided by the JUnit Platform. * *

The purpose of this package is to provide {@code TestEngine} and * {@code Extension} authors convenient access to a subset of internal utility * methods to assist with their implementation. This prevents re-inventing the * wheel and ensures that common tasks are handled in third-party engines and * extensions with the same semantics as within the JUnit Platform itself. */ package org.junit.platform.commons.support; junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/000077500000000000000000000000001455764576500305035ustar00rootroot00000000000000AnnotationUtils.java000066400000000000000000000467201455764576500344330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode; /** * Collection of utilities for working with {@linkplain Annotation annotations}. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * *

Some utilities are published via the maintained {@code AnnotationSupport} * class. * * @since 1.0 * @see Annotation * @see AnnotatedElement * @see org.junit.platform.commons.support.AnnotationSupport */ @API(status = INTERNAL, since = "1.0") public final class AnnotationUtils { private AnnotationUtils() { /* no-op */ } private static final ConcurrentHashMap, Boolean> repeatableAnnotationContainerCache = // new ConcurrentHashMap<>(16); /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the supplied optional * {@code element}. * * @see #findAnnotation(Optional, Class) * @see org.junit.platform.commons.support.AnnotationSupport#isAnnotated(Optional, Class) */ public static boolean isAnnotated(Optional element, Class annotationType) { return findAnnotation(element, annotationType).isPresent(); } /** * @since 1.8 * @see #findAnnotation(Parameter, int, Class) */ public static boolean isAnnotated(Parameter parameter, int index, Class annotationType) { return findAnnotation(parameter, index, annotationType).isPresent(); } /** * Determine if an annotation of {@code annotationType} is either * present or meta-present on the supplied * {@code element}. * * @param element the element on which to search for the annotation; may be * {@code null} * @param annotationType the annotation type to search for; never {@code null} * @return {@code true} if the annotation is present or meta-present * @see #findAnnotation(AnnotatedElement, Class) * @see org.junit.platform.commons.support.AnnotationSupport#isAnnotated(AnnotatedElement, Class) */ public static boolean isAnnotated(AnnotatedElement element, Class annotationType) { return findAnnotation(element, annotationType).isPresent(); } /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(Optional, Class) */ public static Optional findAnnotation(Optional element, Class annotationType) { if (element == null || !element.isPresent()) { return Optional.empty(); } return findAnnotation(element.get(), annotationType); } /** * @since 1.8 * @see #findAnnotation(AnnotatedElement, Class) */ public static Optional findAnnotation(Parameter parameter, int index, Class annotationType) { return findAnnotation(getEffectiveAnnotatedParameter(parameter, index), annotationType); } /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(AnnotatedElement, Class) */ public static Optional findAnnotation(AnnotatedElement element, Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); boolean inherited = annotationType.isAnnotationPresent(Inherited.class); return findAnnotation(element, annotationType, inherited, new HashSet<>()); } private static Optional findAnnotation(AnnotatedElement element, Class annotationType, boolean inherited, Set visited) { Preconditions.notNull(annotationType, "annotationType must not be null"); if (element == null) { return Optional.empty(); } // Directly present? A annotation = element.getDeclaredAnnotation(annotationType); if (annotation != null) { return Optional.of(annotation); } // Meta-present on directly present annotations? Optional directMetaAnnotation = findMetaAnnotation(annotationType, element.getDeclaredAnnotations(), inherited, visited); if (directMetaAnnotation.isPresent()) { return directMetaAnnotation; } if (element instanceof Class) { Class clazz = (Class) element; // Search on interfaces for (Class ifc : clazz.getInterfaces()) { if (ifc != Annotation.class) { Optional annotationOnInterface = findAnnotation(ifc, annotationType, inherited, visited); if (annotationOnInterface.isPresent()) { return annotationOnInterface; } } } // Indirectly present? // Search in class hierarchy if (inherited) { Class superclass = clazz.getSuperclass(); if (superclass != null && superclass != Object.class) { Optional annotationOnSuperclass = findAnnotation(superclass, annotationType, inherited, visited); if (annotationOnSuperclass.isPresent()) { return annotationOnSuperclass; } } } } // Meta-present on indirectly present annotations? return findMetaAnnotation(annotationType, element.getAnnotations(), inherited, visited); } private static Optional findMetaAnnotation(Class annotationType, Annotation[] candidates, boolean inherited, Set visited) { for (Annotation candidateAnnotation : candidates) { Class candidateAnnotationType = candidateAnnotation.annotationType(); if (!isInJavaLangAnnotationPackage(candidateAnnotationType) && visited.add(candidateAnnotation)) { Optional metaAnnotation = findAnnotation(candidateAnnotationType, annotationType, inherited, visited); if (metaAnnotation.isPresent()) { return metaAnnotation; } } } return Optional.empty(); } /** * Find the first annotation of the specified type that is either * directly present, meta-present, or indirectly * present on the supplied class, optionally searching recursively * through the enclosing class hierarchy if not found on the supplied class. * *

The enclosing class hierarchy will only be searched above an inner * class (i.e., a non-static member class). * * @param the annotation type * @param clazz the class on which to search for the annotation; may be {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param searchEnclosingClasses whether the enclosing class hierarchy should * be searched * @return an {@code Optional} containing the annotation; never {@code null} but * potentially empty * @since 1.8 * @see #findAnnotation(AnnotatedElement, Class) */ public static Optional findAnnotation(Class clazz, Class annotationType, boolean searchEnclosingClasses) { Preconditions.notNull(annotationType, "annotationType must not be null"); if (!searchEnclosingClasses) { return findAnnotation(clazz, annotationType); } Class candidate = clazz; while (candidate != null) { Optional annotation = findAnnotation(candidate, annotationType); if (annotation.isPresent()) { return annotation; } candidate = (isInnerClass(candidate) ? candidate.getEnclosingClass() : null); } return Optional.empty(); } /** * @since 1.5 * @see org.junit.platform.commons.support.AnnotationSupport#findRepeatableAnnotations(Optional, Class) */ public static List findRepeatableAnnotations(Optional element, Class annotationType) { if (element == null || !element.isPresent()) { return Collections.emptyList(); } return findRepeatableAnnotations(element.get(), annotationType); } /** * @since 1.8 * @see #findRepeatableAnnotations(AnnotatedElement, Class) */ public static List findRepeatableAnnotations(Parameter parameter, int index, Class annotationType) { return findRepeatableAnnotations(getEffectiveAnnotatedParameter(parameter, index), annotationType); } /** * @see org.junit.platform.commons.support.AnnotationSupport#findRepeatableAnnotations(AnnotatedElement, Class) */ public static List findRepeatableAnnotations(AnnotatedElement element, Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); Repeatable repeatable = annotationType.getAnnotation(Repeatable.class); Preconditions.notNull(repeatable, () -> annotationType.getName() + " must be @Repeatable"); Class containerType = repeatable.value(); boolean inherited = containerType.isAnnotationPresent(Inherited.class); // Short circuit the search algorithm. if (element == null) { return Collections.emptyList(); } // We use a LinkedHashSet because the search algorithm may discover // duplicates, but we need to maintain the original order. Set found = new LinkedHashSet<>(16); findRepeatableAnnotations(element, annotationType, containerType, inherited, found, new HashSet<>(16)); // unmodifiable since returned from public, non-internal method(s) return Collections.unmodifiableList(new ArrayList<>(found)); } private static void findRepeatableAnnotations(AnnotatedElement element, Class annotationType, Class containerType, boolean inherited, Set found, Set visited) { if (element instanceof Class) { Class clazz = (Class) element; // Recurse first in order to support top-down semantics for inherited, repeatable annotations. if (inherited) { Class superclass = clazz.getSuperclass(); if (superclass != null && superclass != Object.class) { findRepeatableAnnotations(superclass, annotationType, containerType, inherited, found, visited); } } // Search on interfaces for (Class ifc : clazz.getInterfaces()) { if (ifc != Annotation.class) { findRepeatableAnnotations(ifc, annotationType, containerType, inherited, found, visited); } } } // Find annotations that are directly present or meta-present on directly present annotations. findRepeatableAnnotations(element.getDeclaredAnnotations(), annotationType, containerType, inherited, found, visited); // Find annotations that are indirectly present or meta-present on indirectly present annotations. findRepeatableAnnotations(element.getAnnotations(), annotationType, containerType, inherited, found, visited); } @SuppressWarnings("unchecked") private static void findRepeatableAnnotations(Annotation[] candidates, Class annotationType, Class containerType, boolean inherited, Set found, Set visited) { for (Annotation candidate : candidates) { Class candidateAnnotationType = candidate.annotationType(); if (!isInJavaLangAnnotationPackage(candidateAnnotationType) && visited.add(candidate)) { // Exact match? if (candidateAnnotationType.equals(annotationType)) { found.add(annotationType.cast(candidate)); } // Container? else if (candidateAnnotationType.equals(containerType)) { // Note: it's not a legitimate containing annotation type if it doesn't declare // a 'value' attribute that returns an array of the contained annotation type. // See https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.3 Method method = ReflectionUtils.tryToGetMethod(containerType, "value").getOrThrow( cause -> new JUnitException(String.format( "Container annotation type '%s' must declare a 'value' attribute of type %s[].", containerType, annotationType), cause)); Annotation[] containedAnnotations = (Annotation[]) ReflectionUtils.invokeMethod(method, candidate); found.addAll((Collection) asList(containedAnnotations)); } // Nested container annotation? else if (isRepeatableAnnotationContainer(candidateAnnotationType)) { Method method = ReflectionUtils.tryToGetMethod(candidateAnnotationType, "value").toOptional().get(); Annotation[] containedAnnotations = (Annotation[]) ReflectionUtils.invokeMethod(method, candidate); for (Annotation containedAnnotation : containedAnnotations) { findRepeatableAnnotations(containedAnnotation.getClass(), annotationType, containerType, inherited, found, visited); } } // Otherwise search recursively through the meta-annotation hierarchy... else { findRepeatableAnnotations(candidateAnnotationType, annotationType, containerType, inherited, found, visited); } } } } /** * Determine if the supplied annotation type is a container for a repeatable * annotation. * * @since 1.5 */ private static boolean isRepeatableAnnotationContainer(Class candidateContainerType) { return repeatableAnnotationContainerCache.computeIfAbsent(candidateContainerType, candidate -> { // @formatter:off Repeatable repeatable = Arrays.stream(candidate.getMethods()) .filter(attribute -> attribute.getName().equals("value") && attribute.getReturnType().isArray()) .findFirst() .map(attribute -> attribute.getReturnType().getComponentType().getAnnotation(Repeatable.class)) .orElse(null); // @formatter:on return repeatable != null && candidate.equals(repeatable.value()); }); } /** * Due to a bug in {@code javac} on JDK versions prior to JDK 9, looking up * annotations directly on a {@link Parameter} will fail for inner class * constructors. * *

Bug in {@code javac} on JDK versions prior to JDK 9

* *

The parameter annotations array in the compiled byte code for the user's * class excludes an entry for the implicit enclosing instance * parameter for an inner class constructor. * *

Workaround

* *

This method provides a workaround for this off-by-one error by helping * JUnit maintainers and extension authors to access annotations on the preceding * {@link Parameter} object (i.e., {@code index - 1}). If the supplied * {@code index} is zero in such situations this method will return {@code null} * since the parameter for the implicit enclosing instance will never * be annotated. * *

WARNING

* *

The {@code AnnotatedElement} returned by this method should never be cast and * treated as a {@code Parameter} since the metadata (e.g., {@link Parameter#getName()}, * {@link Parameter#getType()}, etc.) will not match those for the declared parameter * at the given index in an inner class constructor for code compiled with JDK 8. * * @return the supplied {@code Parameter}, or the effective {@code Parameter} * if the aforementioned bug is detected, or {@code null} if the bug is detected and * the supplied {@code index} is {@code 0} * @since 1.8 */ private static AnnotatedElement getEffectiveAnnotatedParameter(Parameter parameter, int index) { Preconditions.notNull(parameter, "Parameter must not be null"); Executable executable = parameter.getDeclaringExecutable(); if (executable instanceof Constructor && isInnerClass(executable.getDeclaringClass()) && executable.getParameterAnnotations().length == executable.getParameterCount() - 1) { if (index == 0) { return null; } return executable.getParameters()[index - 1]; } return parameter; } /** * @see org.junit.platform.commons.support.AnnotationSupport#findPublicAnnotatedFields(Class, Class, Class) */ public static List findPublicAnnotatedFields(Class clazz, Class fieldType, Class annotationType) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(fieldType, "fieldType must not be null"); Preconditions.notNull(annotationType, "annotationType must not be null"); // @formatter:off return Arrays.stream(clazz.getFields()) .filter(field -> fieldType.isAssignableFrom(field.getType()) && isAnnotated(field, annotationType)) .collect(toUnmodifiableList()); // @formatter:on } /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotatedFields(Class, Class, Predicate) * @see #findAnnotatedFields(Class, Class, Predicate, HierarchyTraversalMode) */ public static List findAnnotatedFields(Class clazz, Class annotationType, Predicate predicate) { return findAnnotatedFields(clazz, annotationType, predicate, HierarchyTraversalMode.TOP_DOWN); } /** * Find all {@linkplain Field fields} of the supplied class or interface * that are annotated or meta-annotated with the specified * {@code annotationType} and match the specified {@code predicate}. * * @param clazz the class or interface in which to find the fields; never {@code null} * @param annotationType the annotation type to search for; never {@code null} * @param predicate the field filter; never {@code null} * @param traversalMode the hierarchy traversal mode; never {@code null} * @return the list of all such fields found; neither {@code null} nor mutable */ public static List findAnnotatedFields(Class clazz, Class annotationType, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(annotationType, "annotationType must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); Predicate annotated = field -> isAnnotated(field, annotationType); return ReflectionUtils.findFields(clazz, annotated.and(predicate), traversalMode); } /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotatedMethods(Class, Class, org.junit.platform.commons.support.HierarchyTraversalMode) */ public static List findAnnotatedMethods(Class clazz, Class annotationType, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(annotationType, "annotationType must not be null"); return ReflectionUtils.findMethods(clazz, method -> isAnnotated(method, annotationType), traversalMode); } private static boolean isInJavaLangAnnotationPackage(Class annotationType) { return (annotationType != null && annotationType.getName().startsWith("java.lang.annotation")); } } BlacklistedExceptions.java000066400000000000000000000031361455764576500355550ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; /** * Internal utilities for working with unrecoverable exceptions. * *

Unrecoverable exceptions are those that should always terminate * test plan execution immediately. * *

Currently Unrecoverable Exceptions

*
    *
  • {@link OutOfMemoryError}
  • *
* *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 * @deprecated Use {@link UnrecoverableExceptions} instead. */ @Deprecated @API(status = DEPRECATED, since = "1.7") public final class BlacklistedExceptions { private BlacklistedExceptions() { /* no-op */ } /** * Rethrow the supplied {@link Throwable exception} if it is * unrecoverable. * *

If the supplied {@code exception} is not unrecoverable, this * method does nothing. * * @deprecated Use {@link UnrecoverableExceptions#rethrowIfUnrecoverable} * instead. */ @Deprecated public static void rethrowIfBlacklisted(Throwable exception) { UnrecoverableExceptions.rethrowIfUnrecoverable(exception); } } ClassFileVisitor.java000066400000000000000000000042521455764576500345170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.nio.file.FileVisitResult.CONTINUE; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.function.Consumer; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * @since 1.0 */ class ClassFileVisitor extends SimpleFileVisitor { private static final Logger logger = LoggerFactory.getLogger(ClassFileVisitor.class); static final String CLASS_FILE_SUFFIX = ".class"; private static final String PACKAGE_INFO_FILE_NAME = "package-info" + CLASS_FILE_SUFFIX; private static final String MODULE_INFO_FILE_NAME = "module-info" + CLASS_FILE_SUFFIX; private final Consumer classFileConsumer; ClassFileVisitor(Consumer classFileConsumer) { this.classFileConsumer = classFileConsumer; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { if (isNotPackageInfo(file) && isNotModuleInfo(file) && isClassFile(file)) { classFileConsumer.accept(file); } return CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException ex) { logger.warn(ex, () -> "I/O error visiting file: " + file); return CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException ex) { if (ex != null) { logger.warn(ex, () -> "I/O error visiting directory: " + dir); } return CONTINUE; } private static boolean isNotPackageInfo(Path path) { return !path.endsWith(PACKAGE_INFO_FILE_NAME); } private static boolean isNotModuleInfo(Path path) { return !path.endsWith(MODULE_INFO_FILE_NAME); } private static boolean isClassFile(Path file) { return file.getFileName().toString().endsWith(CLASS_FILE_SUFFIX); } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassFilter.java000066400000000000000000000043371455764576500335700ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Class-related predicate used by reflection utilities. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.1 */ @API(status = INTERNAL, since = "1.1") public class ClassFilter implements Predicate> { /** * Create a {@link ClassFilter} instance that accepts all names but filters classes. */ public static ClassFilter of(Predicate> classPredicate) { return of(name -> true, classPredicate); } /** * Create a {@link ClassFilter} instance that filters by names and classes. */ public static ClassFilter of(Predicate namePredicate, Predicate> classPredicate) { return new ClassFilter(namePredicate, classPredicate); } private final Predicate namePredicate; private final Predicate> classPredicate; private ClassFilter(Predicate namePredicate, Predicate> classPredicate) { this.namePredicate = Preconditions.notNull(namePredicate, "name predicate must not be null"); this.classPredicate = Preconditions.notNull(classPredicate, "class predicate must not be null"); } /** * Test name using the stored name predicate. */ public boolean match(String name) { return namePredicate.test(name); } /** * Test class using the stored class predicate. */ public boolean match(Class type) { return classPredicate.test(type); } /** * @implNote This implementation combines all tests stored in the predicates * of this instance. Any new predicate must be added to this test method as * well. */ @Override public boolean test(Class type) { return match(type.getName()) && match(type); } } ClassLoaderUtils.java000066400000000000000000000062301455764576500345050ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.net.URL; import java.security.CodeSource; import java.util.Optional; import org.apiguardian.api.API; /** * Collection of utilities for working with {@linkplain ClassLoader} and associated tasks. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class ClassLoaderUtils { private ClassLoaderUtils() { /* no-op */ } /** * Get the {@link ClassLoader} for the supplied {@link Class}, falling back * to the {@link #getDefaultClassLoader() default class loader} if the class * loader for the supplied class is {@code null}. * @param clazz the class for which to retrieve the class loader; never {@code null} * @since 1.10 */ public static ClassLoader getClassLoader(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); ClassLoader classLoader = clazz.getClassLoader(); return (classLoader != null) ? classLoader : getDefaultClassLoader(); } public static ClassLoader getDefaultClassLoader() { try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { return contextClassLoader; } } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); /* otherwise ignore */ } return ClassLoader.getSystemClassLoader(); } /** * Get the location from which the supplied object's class was loaded. * * @param object the object for whose class the location should be retrieved * @return an {@code Optional} containing the URL of the class' location; never * {@code null} but potentially empty */ public static Optional getLocation(Object object) { Preconditions.notNull(object, "object must not be null"); // determine class loader ClassLoader loader = object.getClass().getClassLoader(); if (loader == null) { loader = ClassLoader.getSystemClassLoader(); while (loader != null && loader.getParent() != null) { loader = loader.getParent(); } } // try finding resource by name if (loader != null) { String name = object.getClass().getName(); name = name.replace(".", "/") + ".class"; try { return Optional.ofNullable(loader.getResource(name)); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); /* otherwise ignore */ } } // try protection domain try { CodeSource codeSource = object.getClass().getProtectionDomain().getCodeSource(); if (codeSource != null) { return Optional.ofNullable(codeSource.getLocation()); } } catch (SecurityException ignore) { /* ignore */ } return Optional.empty(); } } ClassNamePatternFilterUtils.java000066400000000000000000000065741455764576500366760ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apiguardian.api.API; /** * Collection of utilities for creating filters based on class names. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.7 */ @API(status = INTERNAL, since = "1.7") public class ClassNamePatternFilterUtils { private ClassNamePatternFilterUtils() { /* no-op */ } public static final String DEACTIVATE_ALL_PATTERN = "*"; /** * Create a {@link Predicate} that can be used to exclude (i.e., filter out) * objects of type {@code T} whose fully qualified class names match any of * the supplied patterns. * * @param patterns a comma-separated list of patterns */ public static Predicate excludeMatchingClasses(String patterns) { return excludeMatchingClasses(patterns, object -> object.getClass().getName()); } /** * Create a {@link Predicate} that can be used to exclude (i.e., filter out) * fully qualified class names matching any of the supplied patterns. * * @param patterns a comma-separated list of patterns */ public static Predicate excludeMatchingClassNames(String patterns) { return excludeMatchingClasses(patterns, Function.identity()); } private static Predicate excludeMatchingClasses(String patterns, Function classNameGetter) { // @formatter:off return Optional.ofNullable(patterns) .filter(StringUtils::isNotBlank) .map(String::trim) .map(trimmedPatterns -> createPredicateFromPatterns(trimmedPatterns, classNameGetter)) .orElse(object -> true); // @formatter:on } private static Predicate createPredicateFromPatterns(String patterns, Function classNameProvider) { if (DEACTIVATE_ALL_PATTERN.equals(patterns)) { return object -> false; } List patternList = convertToRegularExpressions(patterns); return object -> patternList.stream().noneMatch(it -> it.matcher(classNameProvider.apply(object)).matches()); } private static List convertToRegularExpressions(String patterns) { // @formatter:off return Arrays.stream(patterns.split(",")) .filter(StringUtils::isNotBlank) .map(String::trim) .map(ClassNamePatternFilterUtils::replaceRegExElements) .map(Pattern::compile) .collect(toList()); // @formatter:on } private static String replaceRegExElements(String pattern) { return Matcher.quoteReplacement(pattern) // Match "." against "." and "$" since users may declare a "." instead of a // "$" as the separator between classes and nested classes. .replace(".", "[.$]") // Convert our "*" wildcard into a proper RegEx pattern. .replace("*", ".+"); } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassUtils.java000066400000000000000000000060271455764576500334410ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Arrays.stream; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.function.Function; import org.apiguardian.api.API; /** * Collection of utilities for working with {@link Class classes}. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class ClassUtils { private ClassUtils() { /* no-op */ } /** * Get the fully qualified name of the supplied class. * *

This is a null-safe variant of {@link Class#getName()}. * * @param clazz the class whose name should be retrieved, potentially * {@code null} * @return the fully qualified class name or {@code "null"} if the supplied * class reference is {@code null} * @since 1.3 * @see #nullSafeToString(Class...) * @see StringUtils#nullSafeToString(Object) */ public static String nullSafeToString(Class clazz) { return clazz == null ? "null" : clazz.getName(); } /** * Generate a comma-separated list of fully qualified class names for the * supplied classes. * * @param classes the classes whose names should be included in the * generated string * @return a comma-separated list of fully qualified class names, or an empty * string if the supplied class array is {@code null} or empty * @see #nullSafeToString(Function, Class...) * @see StringUtils#nullSafeToString(Object) */ public static String nullSafeToString(Class... classes) { return nullSafeToString(Class::getName, classes); } /** * Generate a comma-separated list of mapped values for the supplied classes. * *

The values are generated by the supplied {@code mapper} * (e.g., {@code Class::getName}, {@code Class::getSimpleName}, etc.), unless * a class reference is {@code null} in which case it will be mapped to * {@code "null"}. * * @param mapper the mapper to use; never {@code null} * @param classes the classes to map * @return a comma-separated list of mapped values, or an empty string if * the supplied class array is {@code null} or empty * @see #nullSafeToString(Class...) * @see StringUtils#nullSafeToString(Object) */ public static String nullSafeToString(Function, ? extends String> mapper, Class... classes) { Preconditions.notNull(mapper, "Mapping function must not be null"); if (classes == null || classes.length == 0) { return ""; } return stream(classes).map(clazz -> clazz == null ? "null" : mapper.apply(clazz)).collect(joining(", ")); } } ClasspathScanner.java000066400000000000000000000224631455764576500345320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.lang.String.format; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.util.ClassFileVisitor.CLASS_FILE_SUFFIX; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import java.io.IOException; import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Stream; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ class ClasspathScanner { private static final Logger logger = LoggerFactory.getLogger(ClasspathScanner.class); private static final char CLASSPATH_RESOURCE_PATH_SEPARATOR = '/'; private static final String CLASSPATH_RESOURCE_PATH_SEPARATOR_STRING = String.valueOf( CLASSPATH_RESOURCE_PATH_SEPARATOR); private static final char PACKAGE_SEPARATOR_CHAR = '.'; private static final String PACKAGE_SEPARATOR_STRING = String.valueOf(PACKAGE_SEPARATOR_CHAR); /** * Malformed class name InternalError like reported in #401. */ private static final String MALFORMED_CLASS_NAME_ERROR_MESSAGE = "Malformed class name"; private final Supplier classLoaderSupplier; private final BiFunction>> loadClass; ClasspathScanner(Supplier classLoaderSupplier, BiFunction>> loadClass) { this.classLoaderSupplier = classLoaderSupplier; this.loadClass = loadClass; } List> scanForClassesInPackage(String basePackageName, ClassFilter classFilter) { Preconditions.condition( PackageUtils.DEFAULT_PACKAGE_NAME.equals(basePackageName) || isNotBlank(basePackageName), "basePackageName must not be null or blank"); Preconditions.notNull(classFilter, "classFilter must not be null"); basePackageName = basePackageName.trim(); return findClassesForUris(getRootUrisForPackageNameOnClassPathAndModulePath(basePackageName), basePackageName, classFilter); } List> scanForClassesInClasspathRoot(URI root, ClassFilter classFilter) { Preconditions.notNull(root, "root must not be null"); Preconditions.notNull(classFilter, "classFilter must not be null"); return findClassesForUri(root, PackageUtils.DEFAULT_PACKAGE_NAME, classFilter); } /** * Recursively scan for classes in all of the supplied source directories. */ private List> findClassesForUris(List baseUris, String basePackageName, ClassFilter classFilter) { // @formatter:off return baseUris.stream() .map(baseUri -> findClassesForUri(baseUri, basePackageName, classFilter)) .flatMap(Collection::stream) .distinct() .collect(toList()); // @formatter:on } private List> findClassesForUri(URI baseUri, String basePackageName, ClassFilter classFilter) { try (CloseablePath closeablePath = CloseablePath.create(baseUri)) { Path baseDir = closeablePath.getPath(); return findClassesForPath(baseDir, basePackageName, classFilter); } catch (PreconditionViolationException ex) { throw ex; } catch (Exception ex) { logger.warn(ex, () -> "Error scanning files for URI " + baseUri); return emptyList(); } } private List> findClassesForPath(Path baseDir, String basePackageName, ClassFilter classFilter) { Preconditions.condition(Files.exists(baseDir), () -> "baseDir must exist: " + baseDir); List> classes = new ArrayList<>(); try { Files.walkFileTree(baseDir, new ClassFileVisitor( classFile -> processClassFileSafely(baseDir, basePackageName, classFilter, classFile, classes::add))); } catch (IOException ex) { logger.warn(ex, () -> "I/O error scanning files in " + baseDir); } return classes; } private void processClassFileSafely(Path baseDir, String basePackageName, ClassFilter classFilter, Path classFile, Consumer> classConsumer) { try { String fullyQualifiedClassName = determineFullyQualifiedClassName(baseDir, basePackageName, classFile); if (classFilter.match(fullyQualifiedClassName)) { try { // @formatter:off loadClass.apply(fullyQualifiedClassName, getClassLoader()) .toOptional() .filter(classFilter) // Always use ".filter(classFilter)" to include future predicates. .ifPresent(classConsumer); // @formatter:on } catch (InternalError internalError) { handleInternalError(classFile, fullyQualifiedClassName, internalError); } } } catch (Throwable throwable) { handleThrowable(classFile, throwable); } } private String determineFullyQualifiedClassName(Path baseDir, String basePackageName, Path classFile) { // @formatter:off return Stream.of( basePackageName, determineSubpackageName(baseDir, classFile), determineSimpleClassName(classFile) ) .filter(value -> !value.isEmpty()) // Handle default package appropriately. .collect(joining(PACKAGE_SEPARATOR_STRING)); // @formatter:on } private String determineSimpleClassName(Path classFile) { String fileName = classFile.getFileName().toString(); return fileName.substring(0, fileName.length() - CLASS_FILE_SUFFIX.length()); } private String determineSubpackageName(Path baseDir, Path classFile) { Path relativePath = baseDir.relativize(classFile.getParent()); String pathSeparator = baseDir.getFileSystem().getSeparator(); String subpackageName = relativePath.toString().replace(pathSeparator, PACKAGE_SEPARATOR_STRING); if (subpackageName.endsWith(pathSeparator)) { // Workaround for JDK bug: https://bugs.openjdk.java.net/browse/JDK-8153248 subpackageName = subpackageName.substring(0, subpackageName.length() - pathSeparator.length()); } return subpackageName; } private void handleInternalError(Path classFile, String fullyQualifiedClassName, InternalError ex) { if (MALFORMED_CLASS_NAME_ERROR_MESSAGE.equals(ex.getMessage())) { logMalformedClassName(classFile, fullyQualifiedClassName, ex); } else { logGenericFileProcessingException(classFile, ex); } } private void handleThrowable(Path classFile, Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logGenericFileProcessingException(classFile, throwable); } private void logMalformedClassName(Path classFile, String fullyQualifiedClassName, InternalError ex) { try { logger.debug(ex, () -> format("The java.lang.Class loaded from path [%s] has a malformed class name [%s].", classFile.toAbsolutePath(), fullyQualifiedClassName)); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); ex.addSuppressed(t); logGenericFileProcessingException(classFile, ex); } } private void logGenericFileProcessingException(Path classFile, Throwable throwable) { logger.debug(throwable, () -> format("Failed to load java.lang.Class for path [%s] during classpath scanning.", classFile.toAbsolutePath())); } private ClassLoader getClassLoader() { return this.classLoaderSupplier.get(); } private List getRootUrisForPackageNameOnClassPathAndModulePath(String basePackageName) { Set uriSet = new LinkedHashSet<>(getRootUrisForPackage(basePackageName)); if (!basePackageName.isEmpty() && !basePackageName.endsWith(PACKAGE_SEPARATOR_STRING)) { getRootUrisForPackage(basePackageName + PACKAGE_SEPARATOR_STRING).stream() // .map(ClasspathScanner::removeTrailingClasspathResourcePathSeparator) // .forEach(uriSet::add); } return new ArrayList<>(uriSet); } private static URI removeTrailingClasspathResourcePathSeparator(URI uri) { String string = uri.toString(); if (string.endsWith(CLASSPATH_RESOURCE_PATH_SEPARATOR_STRING)) { return URI.create(string.substring(0, string.length() - 1)); } return uri; } private static String packagePath(String packageName) { if (packageName.isEmpty()) { return ""; } return packageName.replace(PACKAGE_SEPARATOR_CHAR, CLASSPATH_RESOURCE_PATH_SEPARATOR); } private List getRootUrisForPackage(String basePackageName) { try { Enumeration resources = getClassLoader().getResources(packagePath(basePackageName)); List uris = new ArrayList<>(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); uris.add(resource.toURI()); } return uris; } catch (Exception ex) { logger.warn(ex, () -> "Error reading URIs from class loader for base package " + basePackageName); return emptyList(); } } } CloseablePath.java000066400000000000000000000067751455764576500340140ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Collections.emptyMap; import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; /** * @since 1.0 */ final class CloseablePath implements Closeable { private static final String FILE_URI_SCHEME = "file"; private static final String JAR_URI_SCHEME = "jar"; private static final String JAR_FILE_EXTENSION = ".jar"; private static final String JAR_URI_SEPARATOR = "!"; private static final Closeable NULL_CLOSEABLE = () -> { }; private static final ConcurrentMap MANAGED_FILE_SYSTEMS = new ConcurrentHashMap<>(); private final Path path; private final Closeable delegate; static CloseablePath create(URI uri) throws URISyntaxException { if (JAR_URI_SCHEME.equals(uri.getScheme())) { String[] parts = uri.toString().split(JAR_URI_SEPARATOR); String jarUri = parts[0]; String jarEntry = parts[1]; return createForJarFileSystem(new URI(jarUri), fileSystem -> fileSystem.getPath(jarEntry)); } if (uri.getScheme().equals(FILE_URI_SCHEME) && uri.getPath().endsWith(JAR_FILE_EXTENSION)) { return createForJarFileSystem(new URI(JAR_URI_SCHEME + ':' + uri), fileSystem -> fileSystem.getRootDirectories().iterator().next()); } return new CloseablePath(Paths.get(uri), NULL_CLOSEABLE); } private static CloseablePath createForJarFileSystem(URI jarUri, Function pathProvider) { ManagedFileSystem managedFileSystem = MANAGED_FILE_SYSTEMS.compute(jarUri, (__, oldValue) -> oldValue == null ? new ManagedFileSystem(jarUri) : oldValue.retain()); Path path = pathProvider.apply(managedFileSystem.fileSystem); return new CloseablePath(path, () -> MANAGED_FILE_SYSTEMS.compute(jarUri, (__, ___) -> managedFileSystem.release())); } private CloseablePath(Path path, Closeable delegate) { this.path = path; this.delegate = delegate; } public Path getPath() { return path; } @Override public void close() throws IOException { delegate.close(); } private static class ManagedFileSystem { private final AtomicInteger referenceCount = new AtomicInteger(1); private final FileSystem fileSystem; private final URI jarUri; ManagedFileSystem(URI jarUri) { this.jarUri = jarUri; try { fileSystem = FileSystems.newFileSystem(jarUri, emptyMap()); } catch (IOException e) { throw new UncheckedIOException("Failed to create file system for " + jarUri, e); } } private ManagedFileSystem retain() { referenceCount.incrementAndGet(); return this; } private ManagedFileSystem release() { if (referenceCount.decrementAndGet() == 0) { close(); return null; } return this; } private void close() { try { fileSystem.close(); } catch (IOException e) { throw new UncheckedIOException("Failed to close file system for " + jarUri, e); } } } } CollectionUtils.java000066400000000000000000000165331455764576500344130ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Spliterator.ORDERED; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collector; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; /** * Collection of utilities for working with {@link Collection Collections}. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class CollectionUtils { private CollectionUtils() { /* no-op */ } /** * Read the only element of a collection of size 1. * * @param collection the collection to get the element from * @return the only element of the collection * @throws PreconditionViolationException if the collection is {@code null} * or does not contain exactly one element */ public static T getOnlyElement(Collection collection) { Preconditions.notNull(collection, "collection must not be null"); Preconditions.condition(collection.size() == 1, () -> "collection must contain exactly one element: " + collection); return collection.iterator().next(); } /** * Convert the supplied array of values to a {@link Set}. * * @param values the array of values; never {@code null} * @return a set of the values * @throws PreconditionViolationException if the array is {@code null} * @since 1.6 */ @API(status = INTERNAL, since = "1.6") public static Set toSet(T[] values) { Preconditions.notNull(values, "values array must not be null"); if (values.length == 0) { return Collections.emptySet(); } if (values.length == 1) { return Collections.singleton(values[0]); } Set set = new HashSet<>(); Collections.addAll(set, values); return set; } /** * Return a {@code Collector} that accumulates the input elements into a * new unmodifiable list, in encounter order. * *

There are no guarantees on the type or serializability of the list * returned, so if more control over the returned list is required, * consider creating a new {@code Collector} implementation like the * following: * *

	 * public static <T> Collector<T, ?, List<T>> toUnmodifiableList(Supplier<List<T>> listSupplier) {
	 *     return Collectors.collectingAndThen(Collectors.toCollection(listSupplier), Collections::unmodifiableList);
	 * }
	 * 
* * @param the type of the input elements * @return a {@code Collector} which collects all the input elements into * an unmodifiable list, in encounter order */ public static Collector> toUnmodifiableList() { return collectingAndThen(toList(), Collections::unmodifiableList); } /** * Determine if an instance of the supplied type can be converted into a * {@code Stream}. * *

If this method returns {@code true}, {@link #toStream(Object)} can * successfully convert an object of the specified type into a stream. See * {@link #toStream(Object)} for supported types. * * @param type the type to check; may be {@code null} * @return {@code true} if an instance of the type can be converted into a stream * @since 1.9.1 * @see #toStream(Object) */ @API(status = INTERNAL, since = "1.9.1") public static boolean isConvertibleToStream(Class type) { if (type == null || type == void.class) { return false; } return (Stream.class.isAssignableFrom(type)// || DoubleStream.class.isAssignableFrom(type)// || IntStream.class.isAssignableFrom(type)// || LongStream.class.isAssignableFrom(type)// || Iterable.class.isAssignableFrom(type)// || Iterator.class.isAssignableFrom(type)// || Object[].class.isAssignableFrom(type)// || (type.isArray() && type.getComponentType().isPrimitive())); } /** * Convert an object of one of the following supported types into a {@code Stream}. * *

    *
  • {@link Stream}
  • *
  • {@link DoubleStream}
  • *
  • {@link IntStream}
  • *
  • {@link LongStream}
  • *
  • {@link Collection}
  • *
  • {@link Iterable}
  • *
  • {@link Iterator}
  • *
  • {@link Object} array
  • *
  • primitive array
  • *
* * @param object the object to convert into a stream; never {@code null} * @return the resulting stream * @throws PreconditionViolationException if the supplied object is {@code null} * or not one of the supported types * @see #isConvertibleToStream(Class) */ public static Stream toStream(Object object) { Preconditions.notNull(object, "Object must not be null"); if (object instanceof Stream) { return (Stream) object; } if (object instanceof DoubleStream) { return ((DoubleStream) object).boxed(); } if (object instanceof IntStream) { return ((IntStream) object).boxed(); } if (object instanceof LongStream) { return ((LongStream) object).boxed(); } if (object instanceof Collection) { return ((Collection) object).stream(); } if (object instanceof Iterable) { return stream(((Iterable) object).spliterator(), false); } if (object instanceof Iterator) { return stream(spliteratorUnknownSize((Iterator) object, ORDERED), false); } if (object instanceof Object[]) { return Arrays.stream((Object[]) object); } if (object instanceof double[]) { return DoubleStream.of((double[]) object).boxed(); } if (object instanceof int[]) { return IntStream.of((int[]) object).boxed(); } if (object instanceof long[]) { return LongStream.of((long[]) object).boxed(); } if (object.getClass().isArray() && object.getClass().getComponentType().isPrimitive()) { return IntStream.range(0, Array.getLength(object)).mapToObj(i -> Array.get(object, i)); } throw new PreconditionViolationException( "Cannot convert instance of " + object.getClass().getName() + " into a Stream: " + object); } /** * Call the supplied action on each element of the supplied {@link List} from last to first element. */ @API(status = INTERNAL, since = "1.9.2") public static void forEachInReverseOrder(List list, Consumer action) { if (list.isEmpty()) { return; } if (list.size() == 1) { action.accept(list.get(0)); return; } for (ListIterator iterator = list.listIterator(list.size()); iterator.hasPrevious();) { action.accept(iterator.previous()); } } } ExceptionUtils.java000066400000000000000000000135011455764576500342460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Collection of utilities for working with exceptions. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class ExceptionUtils { private static final String JUNIT_PLATFORM_LAUNCHER_PACKAGE_PREFIX = "org.junit.platform.launcher."; private static final Predicate STACK_TRACE_ELEMENT_FILTER = ClassNamePatternFilterUtils // .excludeMatchingClassNames("org.junit.*,jdk.internal.reflect.*,sun.reflect.*"); private ExceptionUtils() { /* no-op */ } /** * Throw the supplied {@link Throwable}, masked as an * unchecked exception. * *

The supplied {@code Throwable} will not be wrapped. Rather, it * will be thrown as is using an exploit of the Java language * that relies on a combination of generics and type erasure to trick * the Java compiler into believing that the thrown exception is an * unchecked exception even if it is a checked exception. * *

Warning

* *

This method should be used sparingly. * * @param t the {@code Throwable} to throw as an unchecked exception; * never {@code null} * @return this method always throws an exception and therefore never * returns anything; the return type is merely present to allow this * method to be supplied as the operand in a {@code throw} statement */ public static RuntimeException throwAsUncheckedException(Throwable t) { Preconditions.notNull(t, "Throwable must not be null"); ExceptionUtils.throwAs(t); // Appeasing the compiler: the following line will never be executed. return null; } @SuppressWarnings("unchecked") private static void throwAs(Throwable t) throws T { throw (T) t; } /** * Read the stacktrace of the supplied {@link Throwable} into a String. */ public static String readStackTrace(Throwable throwable) { Preconditions.notNull(throwable, "Throwable must not be null"); StringWriter stringWriter = new StringWriter(); try (PrintWriter printWriter = new PrintWriter(stringWriter)) { throwable.printStackTrace(printWriter); } return stringWriter.toString(); } /** * Prune the stack trace of the supplied {@link Throwable} by removing * {@linkplain StackTraceElement stack trace elements} from the {@code org.junit}, * {@code jdk.internal.reflect}, and {@code sun.reflect} packages. If a * {@code StackTraceElement} matching one of the supplied {@code classNames} * is encountered, all subsequent elements in the stack trace will be retained. * *

Additionally, all elements prior to and including the first JUnit Platform * Launcher call will be removed. * * @param throwable the {@code Throwable} whose stack trace should be pruned; * never {@code null} * @param classNames the class names that should stop the pruning if encountered; * never {@code null} * * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public static void pruneStackTrace(Throwable throwable, List classNames) { Preconditions.notNull(throwable, "Throwable must not be null"); Preconditions.notNull(classNames, "List of class names must not be null"); List stackTrace = Arrays.asList(throwable.getStackTrace()); List prunedStackTrace = new ArrayList<>(); Collections.reverse(stackTrace); for (int i = 0; i < stackTrace.size(); i++) { StackTraceElement element = stackTrace.get(i); String className = element.getClassName(); if (classNames.contains(className)) { // Include all elements called by the test prunedStackTrace.addAll(stackTrace.subList(i, stackTrace.size())); break; } else if (className.startsWith(JUNIT_PLATFORM_LAUNCHER_PACKAGE_PREFIX)) { prunedStackTrace.clear(); } else if (STACK_TRACE_ELEMENT_FILTER.test(className)) { prunedStackTrace.add(element); } } Collections.reverse(prunedStackTrace); throwable.setStackTrace(prunedStackTrace.toArray(new StackTraceElement[0])); } /** * Find all causes and suppressed exceptions in the stack trace of the * supplied {@link Throwable}. * * @param rootThrowable the {@code Throwable} to explore; never {@code null} * @return an immutable list of all throwables found, including the supplied * one; never {@code null} * * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public static List findNestedThrowables(Throwable rootThrowable) { Preconditions.notNull(rootThrowable, "Throwable must not be null"); Set visited = new LinkedHashSet<>(); Deque toVisit = new ArrayDeque<>(); toVisit.add(rootThrowable); while (!toVisit.isEmpty()) { Throwable current = toVisit.remove(); boolean isFirstVisit = visited.add(current); if (isFirstVisit) { Throwable cause = current.getCause(); if (cause != null) { toVisit.add(cause); } toVisit.addAll(Arrays.asList(current.getSuppressed())); } } return Collections.unmodifiableList(new ArrayList<>(visited)); } } FunctionUtils.java000066400000000000000000000030231455764576500340730ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.function.Function; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Collection of utilities for working with {@link Function Functions}, * {@link Predicate Predicates}, etc. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class FunctionUtils { private FunctionUtils() { /* no-op */ } /** * Return a predicate that first applies the specified function and then * tests the specified predicate against the result of the function. * * @param function the function to apply * @param predicate the predicate to test against the result of the function */ public static Predicate where(Function function, Predicate predicate) { Preconditions.notNull(function, "function must not be null"); Preconditions.notNull(predicate, "predicate must not be null"); return input -> predicate.test(function.apply(input)); } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/LruCache.java000066400000000000000000000027531455764576500330430ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.LinkedHashMap; import java.util.Map; import org.apiguardian.api.API; /** * A simple LRU cache with a maximum size. * *

This class is not thread-safe. * * @param the type of keys maintained by this cache * @param the type of values maintained by this cache * @since 1.6 */ @API(status = INTERNAL, since = "1.6") public class LruCache extends LinkedHashMap { private static final long serialVersionUID = 1L; private final int maxSize; /** * Create a new LRU cache that maintains at most the supplied number of * entries. * *

For optimal use of the internal data structures, you should pick a * number that's one below a power of two since this is based on a * {@link java.util.HashMap} and the eldest entry will be evicted after * adding the entry that increases the {@linkplain #size() size} to be above * {@code maxSize}. */ public LruCache(int maxSize) { super(maxSize + 1, 1, true); this.maxSize = maxSize; } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java000066400000000000000000000060621455764576500336200ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.List; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * Collection of utilities for working with {@code java.lang.Module} * and friends. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.1 */ @API(status = INTERNAL, since = "1.1") public class ModuleUtils { private static final Logger logger = LoggerFactory.getLogger(ModuleUtils.class); /** * Find all non-system boot modules names. * * @return a set of all such module names; never {@code null} but * potentially empty */ public static Set findAllNonSystemBootModuleNames() { logger.config(() -> "Basic version of findAllNonSystemBootModuleNames() always returns an empty set!"); return emptySet(); } /** * Determine if the current Java runtime supports the Java Platform Module System. * * @return {@code true} if the Java Platform Module System is available, * otherwise {@code false} */ public static boolean isJavaPlatformModuleSystemAvailable() { return false; } /** * Return the name of the module that the class or interface is a member of. * * @param type class or interface to analyze * @return the module name; never {@code null} but potentially empty */ public static Optional getModuleName(Class type) { return Optional.empty(); } /** * Return the raw version of the module that the class or interface is a member of. * * @param type class or interface to analyze * @return the raw module version; never {@code null} but potentially empty */ public static Optional getModuleVersion(Class type) { return Optional.empty(); } /** * Find all classes for the given module name. * * @param moduleName the name of the module to scan; never {@code null} or * empty * @param filter the class filter to apply; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty */ public static List> findAllClassesInModule(String moduleName, ClassFilter filter) { Preconditions.notBlank(moduleName, "Module name must not be null or empty"); Preconditions.notNull(filter, "Class filter must not be null"); logger.config(() -> "Basic version of findAllClassesInModule() always returns an empty list!"); return emptyList(); } } PackageUtils.java000066400000000000000000000070401455764576500336440ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.File; import java.net.URL; import java.util.Optional; import java.util.function.Function; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import org.apiguardian.api.API; /** * Collection of utilities for working with {@linkplain Package packages}. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class PackageUtils { private PackageUtils() { /* no-op */ } static final String DEFAULT_PACKAGE_NAME = ""; /** * Get the package attribute for the supplied {@code type} using the * supplied {@code function}. * *

This method only returns a non-empty {@link Optional} value holder * if the class loader for the supplied type created a {@link Package} * object and the supplied function does not return {@code null} when * applied. * * @param type the type to get the package attribute for * @param function a function that computes the package attribute value * (e.g., {@code Package::getImplementationTitle}); never {@code null} * @return an {@code Optional} containing the attribute value; never * {@code null} but potentially empty * @throws org.junit.platform.commons.PreconditionViolationException if the * supplied type or function is {@code null} * @see Class#getPackage() * @see Package#getImplementationTitle() * @see Package#getImplementationVersion() */ public static Optional getAttribute(Class type, Function function) { Preconditions.notNull(type, "type must not be null"); Preconditions.notNull(function, "function must not be null"); return Optional.ofNullable(type.getPackage()).map(function); } /** * Get the value of the specified attribute name, specified as a string, * or an empty {@link Optional} if the attribute was not found. The attribute * name is case-insensitive. * *

This method also returns an empty {@link Optional} value holder * if any exception is caught while loading the manifest file via the * JAR file of the specified type. * * @param type the type to get the attribute for * @param name the attribute name as a string * @return an {@code Optional} containing the attribute value; never * {@code null} but potentially empty * @throws org.junit.platform.commons.PreconditionViolationException if the * supplied type is {@code null} or the specified name is blank * @see Manifest#getMainAttributes() */ public static Optional getAttribute(Class type, String name) { Preconditions.notNull(type, "type must not be null"); Preconditions.notBlank(name, "name must not be blank"); try { URL jarUrl = type.getProtectionDomain().getCodeSource().getLocation(); try (JarFile jarFile = new JarFile(new File(jarUrl.toURI()))) { Attributes mainAttributes = jarFile.getManifest().getMainAttributes(); return Optional.ofNullable(mainAttributes.getValue(name)); } } catch (Exception e) { return Optional.empty(); } } } PreconditionViolationException.java000066400000000000000000000020341455764576500374670ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Thrown if a precondition is violated. * * @since 1.0 * @see Preconditions * @deprecated Use {@linkplain org.junit.platform.commons.PreconditionViolationException} instead. */ @API(status = DEPRECATED, since = "1.5") @Deprecated public class PreconditionViolationException extends JUnitException { private static final long serialVersionUID = 1L; public PreconditionViolationException(String message) { super(message); } public PreconditionViolationException(String message, Throwable cause) { super(message, cause); } } Preconditions.java000066400000000000000000000257461455764576500341250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; import java.util.Collection; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; /** * Collection of utilities for asserting preconditions for method and * constructor arguments. * *

Each method in this class throws a {@link PreconditionViolationException} * if the precondition is violated. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class Preconditions { private Preconditions() { /* no-op */ } /** * Assert that the supplied {@link Object} is not {@code null}. * * @param object the object to check * @param message precondition violation message * @return the supplied object as a convenience * @throws PreconditionViolationException if the supplied object is {@code null} * @see #notNull(Object, Supplier) */ public static T notNull(T object, String message) throws PreconditionViolationException { condition(object != null, message); return object; } /** * Assert that the supplied {@link Object} is not {@code null}. * * @param object the object to check * @param messageSupplier precondition violation message supplier * @return the supplied object as a convenience * @throws PreconditionViolationException if the supplied object is {@code null} * @see #condition(boolean, Supplier) */ public static T notNull(T object, Supplier messageSupplier) throws PreconditionViolationException { condition(object != null, messageSupplier); return object; } /** * Assert that the supplied array is neither {@code null} nor empty. * * @param array the array to check * @param message precondition violation message * @return the supplied array as a convenience * @throws PreconditionViolationException if the supplied array is * {@code null} or empty * @since 1.9 * @see #condition(boolean, String) */ @API(status = EXPERIMENTAL, since = "1.9") public static int[] notEmpty(int[] array, String message) throws PreconditionViolationException { condition(array != null && array.length > 0, message); return array; } /** * Assert that the supplied array is neither {@code null} nor empty. * *

WARNING: this method does NOT check if the supplied * array contains any {@code null} elements. * * @param array the array to check * @param message precondition violation message * @return the supplied array as a convenience * @throws PreconditionViolationException if the supplied array is * {@code null} or empty * @see #containsNoNullElements(Object[], String) * @see #condition(boolean, String) */ public static T[] notEmpty(T[] array, String message) throws PreconditionViolationException { condition(array != null && array.length > 0, message); return array; } /** * Assert that the supplied array is neither {@code null} nor empty. * *

WARNING: this method does NOT check if the supplied * array contains any {@code null} elements. * * @param array the array to check * @param messageSupplier precondition violation message supplier * @return the supplied array as a convenience * @throws PreconditionViolationException if the supplied array is * {@code null} or empty * @see #containsNoNullElements(Object[], String) * @see #condition(boolean, String) */ public static T[] notEmpty(T[] array, Supplier messageSupplier) throws PreconditionViolationException { condition(array != null && array.length > 0, messageSupplier); return array; } /** * Assert that the supplied {@link Collection} is neither {@code null} nor empty. * *

WARNING: this method does NOT check if the supplied * collection contains any {@code null} elements. * * @param collection the collection to check * @param message precondition violation message * @return the supplied collection as a convenience * @throws PreconditionViolationException if the supplied collection is {@code null} or empty * @see #containsNoNullElements(Collection, String) * @see #condition(boolean, String) */ public static > T notEmpty(T collection, String message) throws PreconditionViolationException { condition(collection != null && !collection.isEmpty(), message); return collection; } /** * Assert that the supplied {@link Collection} is neither {@code null} nor empty. * *

WARNING: this method does NOT check if the supplied * collection contains any {@code null} elements. * * @param collection the collection to check * @param messageSupplier precondition violation message supplier * @return the supplied collection as a convenience * @throws PreconditionViolationException if the supplied collection is {@code null} or empty * @see #containsNoNullElements(Collection, String) * @see #condition(boolean, String) */ public static > T notEmpty(T collection, Supplier messageSupplier) throws PreconditionViolationException { condition(collection != null && !collection.isEmpty(), messageSupplier); return collection; } /** * Assert that the supplied array contains no {@code null} elements. * *

WARNING: this method does NOT check if the supplied * array is {@code null} or empty. * * @param array the array to check * @param message precondition violation message * @return the supplied array as a convenience * @throws PreconditionViolationException if the supplied array contains * any {@code null} elements * @see #notNull(Object, String) */ public static T[] containsNoNullElements(T[] array, String message) throws PreconditionViolationException { if (array != null) { Arrays.stream(array).forEach(object -> notNull(object, message)); } return array; } /** * Assert that the supplied array contains no {@code null} elements. * *

WARNING: this method does NOT check if the supplied * array is {@code null} or empty. * * @param array the array to check * @param messageSupplier precondition violation message supplier * @return the supplied array as a convenience * @throws PreconditionViolationException if the supplied array contains * any {@code null} elements * @see #notNull(Object, String) */ public static T[] containsNoNullElements(T[] array, Supplier messageSupplier) throws PreconditionViolationException { if (array != null) { Arrays.stream(array).forEach(object -> notNull(object, messageSupplier)); } return array; } /** * Assert that the supplied collection contains no {@code null} elements. * *

WARNING: this method does NOT check if the supplied * collection is {@code null} or empty. * * @param collection the collection to check * @param message precondition violation message * @return the supplied collection as a convenience * @throws PreconditionViolationException if the supplied collection contains * any {@code null} elements * @see #notNull(Object, String) */ public static > T containsNoNullElements(T collection, String message) throws PreconditionViolationException { if (collection != null) { collection.forEach(object -> notNull(object, message)); } return collection; } /** * Assert that the supplied collection contains no {@code null} elements. * *

WARNING: this method does NOT check if the supplied * collection is {@code null} or empty. * * @param collection the collection to check * @param messageSupplier precondition violation message supplier * @return the supplied collection as a convenience * @throws PreconditionViolationException if the supplied collection contains * any {@code null} elements * @see #notNull(Object, String) */ public static > T containsNoNullElements(T collection, Supplier messageSupplier) throws PreconditionViolationException { if (collection != null) { collection.forEach(object -> notNull(object, messageSupplier)); } return collection; } /** * Assert that the supplied {@link String} is not blank. * *

A {@code String} is blank if it is {@code null} or consists * only of whitespace characters. * * @param str the string to check * @param message precondition violation message * @return the supplied string as a convenience * @throws PreconditionViolationException if the supplied string is blank * @see #notBlank(String, Supplier) */ public static String notBlank(String str, String message) throws PreconditionViolationException { condition(StringUtils.isNotBlank(str), message); return str; } /** * Assert that the supplied {@link String} is not blank. * *

A {@code String} is blank if it is {@code null} or consists * only of whitespace characters. * * @param str the string to check * @param messageSupplier precondition violation message supplier * @return the supplied string as a convenience * @throws PreconditionViolationException if the supplied string is blank * @see StringUtils#isNotBlank(String) * @see #condition(boolean, Supplier) */ public static String notBlank(String str, Supplier messageSupplier) throws PreconditionViolationException { condition(StringUtils.isNotBlank(str), messageSupplier); return str; } /** * Assert that the supplied {@code predicate} is {@code true}. * * @param predicate the predicate to check * @param message precondition violation message * @throws PreconditionViolationException if the predicate is {@code false} * @see #condition(boolean, Supplier) */ public static void condition(boolean predicate, String message) throws PreconditionViolationException { if (!predicate) { throw new PreconditionViolationException(message); } } /** * Assert that the supplied {@code predicate} is {@code true}. * * @param predicate the predicate to check * @param messageSupplier precondition violation message supplier * @throws PreconditionViolationException if the predicate is {@code false} */ public static void condition(boolean predicate, Supplier messageSupplier) throws PreconditionViolationException { if (!predicate) { throw new PreconditionViolationException(messageSupplier.get()); } } } ReflectionUtils.java000066400000000000000000002016141455764576500344060ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.lang.String.format; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; import java.io.File; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * Collection of utilities for working with the Java reflection APIs. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * *

Some utilities are published via the maintained {@code ReflectionSupport} * class. * * @since 1.0 * @see org.junit.platform.commons.support.ReflectionSupport */ @API(status = INTERNAL, since = "1.0") public final class ReflectionUtils { private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class); private ReflectionUtils() { /* no-op */ } /** * Modes in which a hierarchy can be traversed — for example, when * searching for methods or fields within a class hierarchy. */ public enum HierarchyTraversalMode { /** * Traverse the hierarchy using top-down semantics. */ TOP_DOWN, /** * Traverse the hierarchy using bottom-up semantics. */ BOTTOM_UP; } // Pattern: "[Ljava.lang.String;", "[[[[Ljava.lang.String;", etc. private static final Pattern VM_INTERNAL_OBJECT_ARRAY_PATTERN = Pattern.compile("^(\\[+)L(.+);$"); /** * Pattern: "[x", "[[[[x", etc., where x is Z, B, C, D, F, I, J, S, etc. * *

The pattern intentionally captures the last bracket with the * capital letter so that the combination can be looked up via * {@link #classNameToTypeMap}. For example, the last matched group * will contain {@code "[I"} instead of {@code "I"}. * * @see Class#getName() */ private static final Pattern VM_INTERNAL_PRIMITIVE_ARRAY_PATTERN = Pattern.compile("^(\\[+)(\\[[ZBCDFIJS])$"); // Pattern: "java.lang.String[]", "int[]", "int[][][][]", etc. // ?> => non-capturing atomic group // ++ => possessive quantifier private static final Pattern SOURCE_CODE_SYNTAX_ARRAY_PATTERN = Pattern.compile("^([^\\[\\]]+)((?>\\[\\])++)$"); private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; private static final ClasspathScanner classpathScanner = new ClasspathScanner( ClassLoaderUtils::getDefaultClassLoader, ReflectionUtils::tryToLoadClass); /** * Set of fully qualified class names for which no cycles have been detected * in inner class hierarchies. *

This serves as a cache to avoid repeated cycle detection for classes * that have already been checked. * @since 1.6 * @see #detectInnerClassCycle(Class) */ private static final Set noCyclesDetectedCache = ConcurrentHashMap.newKeySet(); /** * Internal cache of common class names mapped to their types. */ private static final Map> classNameToTypeMap; /** * Internal cache of primitive types mapped to their wrapper types. */ private static final Map, Class> primitiveToWrapperMap; static { // @formatter:off List> commonTypes = Arrays.asList( boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class, boolean[].class, byte[].class, char[].class, short[].class, int[].class, long[].class, float[].class, double[].class, boolean[][].class, byte[][].class, char[][].class, short[][].class, int[][].class, long[][].class, float[][].class, double[][].class, Boolean.class, Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class, String.class, Boolean[].class, Byte[].class, Character[].class, Short[].class, Integer[].class, Long[].class, Float[].class, Double[].class, String[].class, Boolean[][].class, Byte[][].class, Character[][].class, Short[][].class, Integer[][].class, Long[][].class, Float[][].class, Double[][].class, String[][].class ); // @formatter:on Map> classNamesToTypes = new HashMap<>(64); commonTypes.forEach(type -> { classNamesToTypes.put(type.getName(), type); classNamesToTypes.put(type.getCanonicalName(), type); }); classNameToTypeMap = Collections.unmodifiableMap(classNamesToTypes); Map, Class> primitivesToWrappers = new IdentityHashMap<>(8); primitivesToWrappers.put(boolean.class, Boolean.class); primitivesToWrappers.put(byte.class, Byte.class); primitivesToWrappers.put(char.class, Character.class); primitivesToWrappers.put(short.class, Short.class); primitivesToWrappers.put(int.class, Integer.class); primitivesToWrappers.put(long.class, Long.class); primitivesToWrappers.put(float.class, Float.class); primitivesToWrappers.put(double.class, Double.class); primitiveToWrapperMap = Collections.unmodifiableMap(primitivesToWrappers); } public static boolean isPublic(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isPublic(clazz.getModifiers()); } public static boolean isPublic(Member member) { Preconditions.notNull(member, "Member must not be null"); return Modifier.isPublic(member.getModifiers()); } public static boolean isPrivate(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isPrivate(clazz.getModifiers()); } public static boolean isPrivate(Member member) { Preconditions.notNull(member, "Member must not be null"); return Modifier.isPrivate(member.getModifiers()); } @API(status = INTERNAL, since = "1.4") public static boolean isNotPrivate(Class clazz) { return !isPrivate(clazz); } @API(status = INTERNAL, since = "1.1") public static boolean isNotPrivate(Member member) { return !isPrivate(member); } public static boolean isAbstract(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isAbstract(clazz.getModifiers()); } public static boolean isAbstract(Member member) { Preconditions.notNull(member, "Member must not be null"); return Modifier.isAbstract(member.getModifiers()); } public static boolean isStatic(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isStatic(clazz.getModifiers()); } @API(status = INTERNAL, since = "1.4") public static boolean isNotStatic(Class clazz) { return !isStatic(clazz); } public static boolean isStatic(Member member) { Preconditions.notNull(member, "Member must not be null"); return Modifier.isStatic(member.getModifiers()); } @API(status = INTERNAL, since = "1.1") public static boolean isNotStatic(Member member) { return !isStatic(member); } /** * @since 1.5 */ @API(status = INTERNAL, since = "1.5") public static boolean isFinal(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isFinal(clazz.getModifiers()); } /** * @since 1.5 */ @API(status = INTERNAL, since = "1.5") public static boolean isNotFinal(Class clazz) { return !isFinal(clazz); } /** * @since 1.5 */ @API(status = INTERNAL, since = "1.5") public static boolean isFinal(Member member) { Preconditions.notNull(member, "Member must not be null"); return Modifier.isFinal(member.getModifiers()); } /** * @since 1.5 */ @API(status = INTERNAL, since = "1.5") public static boolean isNotFinal(Member member) { return !isFinal(member); } /** * Determine if the supplied class is an inner class (i.e., a * non-static member class). * *

Technically speaking (i.e., according to the Java Language * Specification), "an inner class may be a non-static member class, a * local class, or an anonymous class." However, this method does not * return {@code true} for a local or anonymous class. * * @param clazz the class to check; never {@code null} * @return {@code true} if the class is an inner class */ public static boolean isInnerClass(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return !isStatic(clazz) && clazz.isMemberClass(); } public static boolean returnsVoid(Method method) { return method.getReturnType().equals(Void.TYPE); } /** * Determine if the supplied object is an array. * * @param obj the object to test; potentially {@code null} * @return {@code true} if the object is an array */ public static boolean isArray(Object obj) { return (obj != null && obj.getClass().isArray()); } /** * Determine if the supplied object is a multidimensional array. * * @param obj the object to test; potentially {@code null} * @return {@code true} if the object is a multidimensional array * @since 1.3.2 */ @API(status = INTERNAL, since = "1.3.2") public static boolean isMultidimensionalArray(Object obj) { return (obj != null && obj.getClass().isArray() && obj.getClass().getComponentType().isArray()); } /** * Determine if an object of the supplied source type can be assigned to the * supplied target type for the purpose of reflective method invocations. * *

In contrast to {@link Class#isAssignableFrom(Class)}, this method * returns {@code true} if the target type represents a primitive type whose * wrapper matches the supplied source type. In addition, this method * also supports * * widening conversions for primitive target types. * * @param sourceType the non-primitive target type; never {@code null} * @param targetType the target type; never {@code null} * @return {@code true} if an object of the source type is assignment compatible * with the target type * @since 1.8 * @see Class#isInstance(Object) * @see Class#isAssignableFrom(Class) * @see #isAssignableTo(Object, Class) */ public static boolean isAssignableTo(Class sourceType, Class targetType) { Preconditions.notNull(sourceType, "source type must not be null"); Preconditions.condition(!sourceType.isPrimitive(), "source type must not be a primitive type"); Preconditions.notNull(targetType, "target type must not be null"); if (targetType.isAssignableFrom(sourceType)) { return true; } if (targetType.isPrimitive()) { return sourceType == primitiveToWrapperMap.get(targetType) || isWideningConversion(sourceType, targetType); } return false; } /** * Determine if the supplied object can be assigned to the supplied target * type for the purpose of reflective method invocations. * *

In contrast to {@link Class#isInstance(Object)}, this method returns * {@code true} if the target type represents a primitive type whose * wrapper matches the supplied object's type. In addition, this method * also supports * * widening conversions for primitive types and their corresponding * wrapper types. * *

If the supplied object is {@code null} and the supplied type does not * represent a primitive type, this method returns {@code true}. * * @param obj the object to test for assignment compatibility; potentially {@code null} * @param targetType the type to check against; never {@code null} * @return {@code true} if the object is assignment compatible * @see Class#isInstance(Object) * @see Class#isAssignableFrom(Class) * @see #isAssignableTo(Class, Class) */ public static boolean isAssignableTo(Object obj, Class targetType) { Preconditions.notNull(targetType, "target type must not be null"); if (obj == null) { return !targetType.isPrimitive(); } if (targetType.isInstance(obj)) { return true; } if (targetType.isPrimitive()) { Class sourceType = obj.getClass(); return sourceType == primitiveToWrapperMap.get(targetType) || isWideningConversion(sourceType, targetType); } return false; } /** * Determine if Java supports a widening primitive conversion from the * supplied source type to the supplied primitive target type. */ static boolean isWideningConversion(Class sourceType, Class targetType) { Preconditions.condition(targetType.isPrimitive(), "targetType must be primitive"); boolean isPrimitive = sourceType.isPrimitive(); boolean isWrapper = primitiveToWrapperMap.containsValue(sourceType); // Neither a primitive nor a wrapper? if (!isPrimitive && !isWrapper) { return false; } if (isPrimitive) { sourceType = primitiveToWrapperMap.get(sourceType); } // @formatter:off if (sourceType == Byte.class) { return targetType == short.class || targetType == int.class || targetType == long.class || targetType == float.class || targetType == double.class; } if (sourceType == Short.class || sourceType == Character.class) { return targetType == int.class || targetType == long.class || targetType == float.class || targetType == double.class; } if (sourceType == Integer.class) { return targetType == long.class || targetType == float.class || targetType == double.class; } if (sourceType == Long.class) { return targetType == float.class || targetType == double.class; } if (sourceType == Float.class) { return targetType == double.class; } // @formatter:on return false; } /** * Get the wrapper type for the supplied primitive type. * * @param type the primitive type for which to retrieve the wrapper type * @return the corresponding wrapper type or {@code null} if the * supplied type is {@code null} or not a primitive type */ public static Class getWrapperType(Class type) { return primitiveToWrapperMap.get(type); } /** * @see org.junit.platform.commons.support.ReflectionSupport#newInstance(Class, Object...) * @see #newInstance(Constructor, Object...) */ public static T newInstance(Class clazz, Object... args) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(args, "Argument array must not be null"); Preconditions.containsNoNullElements(args, "Individual arguments must not be null"); try { Class[] parameterTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new); return newInstance(clazz.getDeclaredConstructor(parameterTypes), args); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(getUnderlyingCause(t)); } } /** * Create a new instance of type {@code T} by invoking the supplied constructor * with the supplied arguments. * *

The constructor will be made accessible if necessary, and any checked * exception will be {@linkplain ExceptionUtils#throwAsUncheckedException masked} * as an unchecked exception. * * @param constructor the constructor to invoke; never {@code null} * @param args the arguments to pass to the constructor * @return the new instance; never {@code null} * @see #newInstance(Class, Object...) * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ public static T newInstance(Constructor constructor, Object... args) { Preconditions.notNull(constructor, "Constructor must not be null"); try { return makeAccessible(constructor).newInstance(args); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(getUnderlyingCause(t)); } } /** * Read the value of a potentially inaccessible or nonexistent field. * *

If the field does not exist or the value of the field is {@code null}, * an empty {@link Optional} will be returned. * * @param clazz the class where the field is declared; never {@code null} * @param fieldName the name of the field; never {@code null} or empty * @param instance the instance from where the value is to be read; may * be {@code null} for a static field * @see #readFieldValue(Field) * @see #readFieldValue(Field, Object) * @deprecated Please use {@link #tryToReadFieldValue(Class, String, Object)} * instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional readFieldValue(Class clazz, String fieldName, T instance) { return tryToReadFieldValue(clazz, fieldName, instance).toOptional(); } /** * Try to read the value of a potentially inaccessible or nonexistent field. * *

If the field does not exist or an exception occurs while reading it, a * failed {@link Try} is returned that contains the corresponding exception. * * @param clazz the class where the field is declared; never {@code null} * @param fieldName the name of the field; never {@code null} or empty * @param instance the instance from where the value is to be read; may * be {@code null} for a static field * @since 1.4 * @see #tryToReadFieldValue(Field) * @see #tryToReadFieldValue(Field, Object) */ @API(status = INTERNAL, since = "1.4") public static Try tryToReadFieldValue(Class clazz, String fieldName, T instance) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(fieldName, "Field name must not be null or blank"); // @formatter:off return Try.call(() -> clazz.getDeclaredField(fieldName)) .andThen(field -> tryToReadFieldValue(field, instance)); // @formatter:on } /** * Read the value of the supplied static field, making it accessible if * necessary and {@linkplain ExceptionUtils#throwAsUncheckedException masking} * any checked exception as an unchecked exception. * *

If the value of the field is {@code null}, an empty {@link Optional} * will be returned. * * @param field the field to read; never {@code null} * @see #readFieldValue(Field, Object) * @see #readFieldValue(Class, String, Object) * @deprecated Please use {@link #tryToReadFieldValue(Field)} instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional readFieldValue(Field field) { return tryToReadFieldValue(field).toOptional(); } /** * Try to read the value of a potentially inaccessible static field. * *

If an exception occurs while reading the field, a failed {@link Try} * is returned that contains the corresponding exception. * * @param field the field to read; never {@code null} * @since 1.4 * @see #tryToReadFieldValue(Field, Object) * @see #tryToReadFieldValue(Class, String, Object) */ @API(status = INTERNAL, since = "1.4") public static Try tryToReadFieldValue(Field field) { return tryToReadFieldValue(field, null); } /** * Read the value of the supplied field, making it accessible if necessary * and {@linkplain ExceptionUtils#throwAsUncheckedException masking} any * checked exception as an unchecked exception. * *

If the value of the field is {@code null}, an empty {@link Optional} * will be returned. * * @param field the field to read; never {@code null} * @param instance the instance from which the value is to be read; may * be {@code null} for a static field * @see #readFieldValue(Field) * @see #readFieldValue(Class, String, Object) * @deprecated Please use {@link #tryToReadFieldValue(Field, Object)} * instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional readFieldValue(Field field, Object instance) { return tryToReadFieldValue(field, instance).toOptional(); } /** * @since 1.4 * @see org.junit.platform.commons.support.ReflectionSupport#tryToReadFieldValue(Field, Object) * @see #tryToReadFieldValue(Class, String, Object) */ @API(status = INTERNAL, since = "1.4") public static Try tryToReadFieldValue(Field field, Object instance) { Preconditions.notNull(field, "Field must not be null"); Preconditions.condition((instance != null || isStatic(field)), () -> String.format("Cannot read non-static field [%s] on a null instance.", field)); return Try.call(() -> makeAccessible(field).get(instance)); } /** * Read the values of the supplied fields, making each field accessible if * necessary and {@linkplain ExceptionUtils#throwAsUncheckedException masking} * any checked exception as an unchecked exception. * * @param fields the list of fields to read; never {@code null} * @param instance the instance from which the values are to be read; may * be {@code null} for static fields * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ public static List readFieldValues(List fields, Object instance) { return readFieldValues(fields, instance, field -> true); } /** * Read the values of the supplied fields, making each field accessible if * necessary, {@linkplain ExceptionUtils#throwAsUncheckedException masking} * any checked exception as an unchecked exception, and filtering out fields * that do not pass the supplied {@code predicate}. * * @param fields the list of fields to read; never {@code null} * @param instance the instance from which the values are to be read; may * be {@code null} for static fields * @param predicate the field filter; never {@code null} * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ public static List readFieldValues(List fields, Object instance, Predicate predicate) { Preconditions.notNull(fields, "fields list must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); // @formatter:off return fields.stream() .filter(predicate) .map(field -> tryToReadFieldValue(field, instance) .getOrThrow(ExceptionUtils::throwAsUncheckedException)) .collect(toUnmodifiableList()); // @formatter:on } /** * @see org.junit.platform.commons.support.ReflectionSupport#invokeMethod(Method, Object, Object...) */ public static Object invokeMethod(Method method, Object target, Object... args) { Preconditions.notNull(method, "Method must not be null"); Preconditions.condition((target != null || isStatic(method)), () -> String.format("Cannot invoke non-static method [%s] on a null target.", method.toGenericString())); try { return makeAccessible(method).invoke(target, args); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(getUnderlyingCause(t)); } } /** * @see org.junit.platform.commons.support.ReflectionSupport#loadClass(String) * @deprecated Please use {@link #tryToLoadClass(String)} instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional> loadClass(String name) { return tryToLoadClass(name).toOptional(); } /** * @since 1.4 * @see org.junit.platform.commons.support.ReflectionSupport#tryToLoadClass(String) */ @API(status = INTERNAL, since = "1.4") public static Try> tryToLoadClass(String name) { return tryToLoadClass(name, ClassLoaderUtils.getDefaultClassLoader()); } /** * Load a class by its primitive name or fully qualified name, * using the supplied {@link ClassLoader}. * *

See {@link org.junit.platform.commons.support.ReflectionSupport#loadClass(String)} * for details on support for class names for arrays. * * @param name the name of the class to load; never {@code null} or blank * @param classLoader the {@code ClassLoader} to use; never {@code null} * @see #loadClass(String) * @deprecated Please use {@link #tryToLoadClass(String, ClassLoader)} * instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional> loadClass(String name, ClassLoader classLoader) { return tryToLoadClass(name, classLoader).toOptional(); } /** * Try to load a class by its primitive name or fully qualified * name, using the supplied {@link ClassLoader}. * *

See {@link org.junit.platform.commons.support.ReflectionSupport#tryToLoadClass(String)} * for details on support for class names for arrays. * * @param name the name of the class to load; never {@code null} or blank * @param classLoader the {@code ClassLoader} to use; never {@code null} * @since 1.4 * @see #tryToLoadClass(String) */ @API(status = INTERNAL, since = "1.4") public static Try> tryToLoadClass(String name, ClassLoader classLoader) { Preconditions.notBlank(name, "Class name must not be null or blank"); Preconditions.notNull(classLoader, "ClassLoader must not be null"); String trimmedName = name.trim(); if (classNameToTypeMap.containsKey(trimmedName)) { return Try.success(classNameToTypeMap.get(trimmedName)); } return Try.call(() -> { Matcher matcher; // Primitive arrays such as "[I", "[[[[D", etc. matcher = VM_INTERNAL_PRIMITIVE_ARRAY_PATTERN.matcher(trimmedName); if (matcher.matches()) { String brackets = matcher.group(1); String componentTypeName = matcher.group(2); // Calculate dimensions by counting brackets. int dimensions = brackets.length(); return loadArrayType(classLoader, componentTypeName, dimensions); } // Object arrays such as "[Ljava.lang.String;", "[[[[Ljava.lang.String;", etc. matcher = VM_INTERNAL_OBJECT_ARRAY_PATTERN.matcher(trimmedName); if (matcher.matches()) { String brackets = matcher.group(1); String componentTypeName = matcher.group(2); // Calculate dimensions by counting brackets. int dimensions = brackets.length(); return loadArrayType(classLoader, componentTypeName, dimensions); } // Arrays such as "java.lang.String[]", "int[]", "int[][][][]", etc. matcher = SOURCE_CODE_SYNTAX_ARRAY_PATTERN.matcher(trimmedName); if (matcher.matches()) { String componentTypeName = matcher.group(1); String bracketPairs = matcher.group(2); // Calculate dimensions by counting bracket pairs. int dimensions = bracketPairs.length() / 2; return loadArrayType(classLoader, componentTypeName, dimensions); } // Fallback to standard VM class loading return Class.forName(trimmedName, false, classLoader); }); } private static Class loadArrayType(ClassLoader classLoader, String componentTypeName, int dimensions) throws ClassNotFoundException { Class componentType = classNameToTypeMap.containsKey(componentTypeName) ? classNameToTypeMap.get(componentTypeName) : Class.forName(componentTypeName, false, classLoader); return Array.newInstance(componentType, new int[dimensions]).getClass(); } /** * Build the fully qualified method name for the method described by the * supplied class and method. * *

Note that the class is not necessarily the class in which the method is * declared. * * @param clazz the class from which the method should be referenced; never {@code null} * @param method the method; never {@code null} * @return fully qualified method name; never {@code null} * @since 1.4 * @see #getFullyQualifiedMethodName(Class, String, Class...) */ public static String getFullyQualifiedMethodName(Class clazz, Method method) { Preconditions.notNull(method, "Method must not be null"); return getFullyQualifiedMethodName(clazz, method.getName(), method.getParameterTypes()); } /** * Build the fully qualified method name for the method described by the * supplied class, method name, and parameter types. * *

Note that the class is not necessarily the class in which the method is * declared. * * @param clazz the class from which the method should be referenced; never {@code null} * @param methodName the name of the method; never {@code null} or blank * @param parameterTypes the parameter types of the method; may be {@code null} or empty * @return fully qualified method name; never {@code null} * @see #getFullyQualifiedMethodName(Class, Method) */ public static String getFullyQualifiedMethodName(Class clazz, String methodName, Class... parameterTypes) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); return String.format("%s#%s(%s)", clazz.getName(), methodName, ClassUtils.nullSafeToString(parameterTypes)); } /** * Parse the supplied fully qualified method name into a 3-element * {@code String[]} with the following content. * *

    *
  • index {@code 0}: the fully qualified class name
  • *
  • index {@code 1}: the name of the method
  • *
  • index {@code 2}: a comma-separated list of parameter types, or a * blank string if the method does not declare any formal parameters
  • *
* * @param fullyQualifiedMethodName a fully qualified method name, * never {@code null} or blank * @return a 3-element array of strings containing the parsed values */ public static String[] parseFullyQualifiedMethodName(String fullyQualifiedMethodName) { Preconditions.notBlank(fullyQualifiedMethodName, "fullyQualifiedMethodName must not be null or blank"); int indexOfFirstHashtag = fullyQualifiedMethodName.indexOf('#'); boolean validSyntax = (indexOfFirstHashtag > 0) && (indexOfFirstHashtag < fullyQualifiedMethodName.length() - 1); Preconditions.condition(validSyntax, () -> "[" + fullyQualifiedMethodName + "] is not a valid fully qualified method name: " + "it must start with a fully qualified class name followed by a '#' " + "and then the method name, optionally followed by a parameter list enclosed in parentheses."); String className = fullyQualifiedMethodName.substring(0, indexOfFirstHashtag); String methodPart = fullyQualifiedMethodName.substring(indexOfFirstHashtag + 1); String methodName = methodPart; String methodParameters = ""; if (methodPart.endsWith("()")) { methodName = methodPart.substring(0, methodPart.length() - 2); } else if (methodPart.endsWith(")")) { int indexOfLastOpeningParenthesis = methodPart.lastIndexOf('('); if ((indexOfLastOpeningParenthesis > 0) && (indexOfLastOpeningParenthesis < methodPart.length() - 1)) { methodName = methodPart.substring(0, indexOfLastOpeningParenthesis); methodParameters = methodPart.substring(indexOfLastOpeningParenthesis + 1, methodPart.length() - 1); } } return new String[] { className, methodName, methodParameters }; } /** * Get the outermost instance of the required type, searching recursively * through enclosing instances. * *

If the supplied inner object is of the required type, it will be * returned. * * @param inner the inner object from which to begin the search; never {@code null} * @param requiredType the required type of the outermost instance; never {@code null} * @return an {@code Optional} containing the outermost instance; never {@code null} * but potentially empty * @deprecated Please discontinue use of this method since it relies on internal * implementation details of the JDK that may not work in the future. */ @API(status = DEPRECATED, since = "1.4") @Deprecated public static Optional getOutermostInstance(Object inner, Class requiredType) { Preconditions.notNull(inner, "inner object must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); if (requiredType.isInstance(inner)) { return Optional.of(inner); } Optional candidate = getOuterInstance(inner); if (candidate.isPresent()) { return getOutermostInstance(candidate.get(), requiredType); } return Optional.empty(); } private static Optional getOuterInstance(Object inner) { // This is risky since it depends on the name of the field which is nowhere guaranteed // but has been stable so far in all JDKs // @formatter:off return Arrays.stream(inner.getClass().getDeclaredFields()) .filter(field -> field.getName().startsWith("this$")) .findFirst() .map(field -> { try { return makeAccessible(field).get(inner); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(t); } }); // @formatter:on } public static Set getAllClasspathRootDirectories() { // This is quite a hack, since sometimes the classpath is quite different String fullClassPath = System.getProperty("java.class.path"); // @formatter:off return Arrays.stream(fullClassPath.split(File.pathSeparator)) .map(Paths::get) .filter(Files::isDirectory) .collect(toSet()); // @formatter:on } /** * @see org.junit.platform.commons.support.ReflectionSupport#findAllClassesInClasspathRoot(URI, Predicate, Predicate) */ public static List> findAllClassesInClasspathRoot(URI root, Predicate> classFilter, Predicate classNameFilter) { // unmodifiable since returned by public, non-internal method(s) return findAllClassesInClasspathRoot(root, ClassFilter.of(classNameFilter, classFilter)); } /** * @since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamAllClassesInClasspathRoot(URI, Predicate, Predicate) */ public static Stream> streamAllClassesInClasspathRoot(URI root, Predicate> classFilter, Predicate classNameFilter) { return streamAllClassesInClasspathRoot(root, ClassFilter.of(classNameFilter, classFilter)); } /** * @since 1.1 */ public static List> findAllClassesInClasspathRoot(URI root, ClassFilter classFilter) { return Collections.unmodifiableList(classpathScanner.scanForClassesInClasspathRoot(root, classFilter)); } /** * @since 1.10 */ public static Stream> streamAllClassesInClasspathRoot(URI root, ClassFilter classFilter) { return findAllClassesInClasspathRoot(root, classFilter).stream(); } /** * @see org.junit.platform.commons.support.ReflectionSupport#findAllClassesInPackage(String, Predicate, Predicate) */ public static List> findAllClassesInPackage(String basePackageName, Predicate> classFilter, Predicate classNameFilter) { // unmodifiable since returned by public, non-internal method(s) return findAllClassesInPackage(basePackageName, ClassFilter.of(classNameFilter, classFilter)); } /** * since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamAllClassesInPackage(String, Predicate, Predicate) */ public static Stream> streamAllClassesInPackage(String basePackageName, Predicate> classFilter, Predicate classNameFilter) { return streamAllClassesInPackage(basePackageName, ClassFilter.of(classNameFilter, classFilter)); } /** * @since 1.1 */ public static List> findAllClassesInPackage(String basePackageName, ClassFilter classFilter) { return Collections.unmodifiableList(classpathScanner.scanForClassesInPackage(basePackageName, classFilter)); } /** * @since 1.10 */ public static Stream> streamAllClassesInPackage(String basePackageName, ClassFilter classFilter) { return findAllClassesInPackage(basePackageName, classFilter).stream(); } /** * @since 1.1.1 * @see org.junit.platform.commons.support.ReflectionSupport#findAllClassesInModule(String, Predicate, Predicate) */ public static List> findAllClassesInModule(String moduleName, Predicate> classFilter, Predicate classNameFilter) { // unmodifiable since returned by public, non-internal method(s) return findAllClassesInModule(moduleName, ClassFilter.of(classNameFilter, classFilter)); } /** * @since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamAllClassesInModule(String, Predicate, Predicate) */ public static Stream> streamAllClassesInModule(String moduleName, Predicate> classFilter, Predicate classNameFilter) { return streamAllClassesInModule(moduleName, ClassFilter.of(classNameFilter, classFilter)); } /** * @since 1.1.1 */ public static List> findAllClassesInModule(String moduleName, ClassFilter classFilter) { return Collections.unmodifiableList(ModuleUtils.findAllClassesInModule(moduleName, classFilter)); } /** * @since 1.10 */ public static Stream> streamAllClassesInModule(String moduleName, ClassFilter classFilter) { return findAllClassesInModule(moduleName, classFilter).stream(); } /** * @see org.junit.platform.commons.support.ReflectionSupport#findNestedClasses(Class, Predicate) */ public static List> findNestedClasses(Class clazz, Predicate> predicate) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); Set> candidates = new LinkedHashSet<>(); findNestedClasses(clazz, predicate, candidates); return Collections.unmodifiableList(new ArrayList<>(candidates)); } /** * since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamNestedClasses(Class, Predicate) */ public static Stream> streamNestedClasses(Class clazz, Predicate> predicate) { return findNestedClasses(clazz, predicate).stream(); } private static void findNestedClasses(Class clazz, Predicate> predicate, Set> candidates) { if (!isSearchable(clazz)) { return; } if (isInnerClass(clazz) && predicate.test(clazz)) { detectInnerClassCycle(clazz); } try { // Candidates in current class for (Class nestedClass : clazz.getDeclaredClasses()) { if (predicate.test(nestedClass)) { detectInnerClassCycle(nestedClass); candidates.add(nestedClass); } } } catch (NoClassDefFoundError error) { logger.debug(error, () -> "Failed to retrieve declared classes for " + clazz.getName()); } // Search class hierarchy findNestedClasses(clazz.getSuperclass(), predicate, candidates); // Search interface hierarchy for (Class ifc : clazz.getInterfaces()) { findNestedClasses(ifc, predicate, candidates); } } /** * Detect a cycle in the inner class hierarchy in which the supplied class * resides — from the supplied class up to the outermost enclosing class * — and throw a {@link JUnitException} if a cycle is detected. * *

This method does not detect cycles within inner class * hierarchies below the supplied class. * *

If the supplied class is not an inner class and does not have a * searchable superclass, this method is effectively a no-op. * * @since 1.6 * @see #isInnerClass(Class) * @see #isSearchable(Class) */ private static void detectInnerClassCycle(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); String className = clazz.getName(); if (noCyclesDetectedCache.contains(className)) { return; } Class superclass = clazz.getSuperclass(); if (isInnerClass(clazz) && isSearchable(superclass)) { for (Class enclosing = clazz.getEnclosingClass(); enclosing != null; enclosing = enclosing.getEnclosingClass()) { if (superclass.equals(enclosing)) { throw new JUnitException(String.format("Detected cycle in inner class hierarchy between %s and %s", className, enclosing.getName())); } } } noCyclesDetectedCache.add(className); } /** * Get the sole declared, non-synthetic {@link Constructor} for the supplied class. * *

Throws a {@link org.junit.platform.commons.PreconditionViolationException} * if the supplied class declares more than one non-synthetic constructor. * * @param clazz the class to get the constructor for * @return the sole declared constructor; never {@code null} * @see Class#getDeclaredConstructors() * @see Class#isSynthetic() */ @SuppressWarnings("unchecked") public static Constructor getDeclaredConstructor(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); try { List> constructors = Arrays.stream(clazz.getDeclaredConstructors())// .filter(ctor -> !ctor.isSynthetic())// .collect(toList()); Preconditions.condition(constructors.size() == 1, () -> String.format("Class [%s] must declare a single constructor", clazz.getName())); return (Constructor) constructors.get(0); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(getUnderlyingCause(t)); } } /** * Find all constructors in the supplied class that match the supplied predicate. * *

Note that this method may return {@linkplain Class#isSynthetic() synthetic} * constructors. If you wish to ignore synthetic constructors, you may filter * them out with the supplied {@code predicate} or filter them out of the list * returned by this method. * * @param clazz the class in which to search for constructors; never {@code null} * @param predicate the predicate to use to test for a match; never {@code null} * @return an immutable list of all such constructors found; never {@code null} * but potentially empty * @see Class#getDeclaredConstructors() * @see Class#isSynthetic() */ public static List> findConstructors(Class clazz, Predicate> predicate) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); try { // @formatter:off return Arrays.stream(clazz.getDeclaredConstructors()) .filter(predicate) .collect(toUnmodifiableList()); // @formatter:on } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(getUnderlyingCause(t)); } } /** * @see org.junit.platform.commons.support.ReflectionSupport#findFields(Class, Predicate, org.junit.platform.commons.support.HierarchyTraversalMode) */ public static List findFields(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { return streamFields(clazz, predicate, traversalMode).collect(toUnmodifiableList()); } /** * @since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamFields(Class, Predicate, org.junit.platform.commons.support.HierarchyTraversalMode) */ public static Stream streamFields(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); return findAllFieldsInHierarchy(clazz, traversalMode).stream().filter(predicate); } private static List findAllFieldsInHierarchy(Class clazz, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); // @formatter:off List localFields = getDeclaredFields(clazz).stream() .filter(field -> !field.isSynthetic()) .collect(toList()); List superclassFields = getSuperclassFields(clazz, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localFields)) .collect(toList()); List interfaceFields = getInterfaceFields(clazz, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localFields)) .collect(toList()); // @formatter:on List fields = new ArrayList<>(); if (traversalMode == TOP_DOWN) { fields.addAll(superclassFields); fields.addAll(interfaceFields); } fields.addAll(localFields); if (traversalMode == BOTTOM_UP) { fields.addAll(interfaceFields); fields.addAll(superclassFields); } return fields; } /** * Determine if a {@link Method} matching the supplied {@link Predicate} * is present within the type hierarchy of the specified class, beginning * with the specified class or interface and traversing up the type * hierarchy until such a method is found or the type hierarchy is exhausted. * * @param clazz the class or interface in which to find the method; never * {@code null} * @param predicate the predicate to use to test for a match; never * {@code null} * @return {@code true} if such a method is present * @see #findMethod(Class, String, String) * @see #findMethod(Class, String, Class...) */ public static boolean isMethodPresent(Class clazz, Predicate predicate) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); return findMethod(clazz, predicate).isPresent(); } /** * Get the {@link Method} in the specified class with the specified name * and parameter types. * *

This method delegates to {@link Class#getMethod(String, Class...)} but * swallows any exception thrown. * * @param clazz the class in which to search for the method; never {@code null} * @param methodName the name of the method to get; never {@code null} or blank * @param parameterTypes the parameter types of the method; may be {@code null} * or empty * @return an {@code Optional} containing the method; never {@code null} but * empty if the invocation of {@code Class#getMethod()} throws a * {@link NoSuchMethodException} * @deprecated Please use {@link #tryToGetMethod(Class, String, Class[])} * instead. */ @API(status = DEPRECATED, since = "1.4") @Deprecated static Optional getMethod(Class clazz, String methodName, Class... parameterTypes) { return tryToGetMethod(clazz, methodName, parameterTypes).toOptional(); } /** * Try to get the {@link Method} in the specified class with the specified * name and parameter types. * *

This method delegates to {@link Class#getMethod(String, Class...)} but * catches any exception thrown. * * @param clazz the class in which to search for the method; never {@code null} * @param methodName the name of the method to get; never {@code null} or blank * @param parameterTypes the parameter types of the method; may be {@code null} * or empty * @return a successful {@link Try} containing the method or a failed * {@link Try} containing the {@link NoSuchMethodException} thrown by * {@code Class#getMethod()}; never {@code null} * @since 1.4 */ @API(status = INTERNAL, since = "1.4") public static Try tryToGetMethod(Class clazz, String methodName, Class... parameterTypes) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); return Try.call(() -> clazz.getMethod(methodName, parameterTypes)); } /** * @see org.junit.platform.commons.support.ReflectionSupport#findMethod(Class, String, String) */ public static Optional findMethod(Class clazz, String methodName, String parameterTypeNames) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); return findMethod(clazz, methodName, resolveParameterTypes(clazz, methodName, parameterTypeNames)); } @API(status = INTERNAL, since = "1.10") public static Class[] resolveParameterTypes(Class clazz, String methodName, String parameterTypeNames) { if (StringUtils.isBlank(parameterTypeNames)) { return EMPTY_CLASS_ARRAY; } // @formatter:off return Arrays.stream(parameterTypeNames.split(",")) .map(String::trim) .map(typeName -> loadRequiredParameterType(clazz, methodName, typeName)) .toArray(Class[]::new); // @formatter:on } private static Class loadRequiredParameterType(Class clazz, String methodName, String typeName) { ClassLoader classLoader = ClassLoaderUtils.getClassLoader(clazz); // @formatter:off return tryToLoadClass(typeName, classLoader) .getOrThrow(cause -> new JUnitException( String.format("Failed to load parameter type [%s] for method [%s] in class [%s].", typeName, methodName, clazz.getName()), cause)); // @formatter:on } /** * @see org.junit.platform.commons.support.ReflectionSupport#findMethod(Class, String, Class...) */ public static Optional findMethod(Class clazz, String methodName, Class... parameterTypes) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypes, "Parameter types array must not be null"); Preconditions.containsNoNullElements(parameterTypes, "Individual parameter types must not be null"); return findMethod(clazz, method -> hasCompatibleSignature(method, methodName, parameterTypes)); } private static Optional findMethod(Class clazz, Predicate predicate) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); for (Class current = clazz; isSearchable(current); current = current.getSuperclass()) { // Search for match in current type List methods = current.isInterface() ? getMethods(current) : getDeclaredMethods(current, BOTTOM_UP); for (Method method : methods) { if (predicate.test(method)) { return Optional.of(method); } } // Search for match in interfaces implemented by current type for (Class ifc : current.getInterfaces()) { Optional optional = findMethod(ifc, predicate); if (optional.isPresent()) { return optional; } } } return Optional.empty(); } /** * Find the first {@link Method} of the supplied class or interface that * meets the specified criteria, beginning with the specified class or * interface and traversing up the type hierarchy until such a method is * found or the type hierarchy is exhausted. * *

Use this method as an alternative to * {@link #findMethod(Class, String, Class...)} for use cases in which the * method is required to be present. * * @param clazz the class or interface in which to find the method; * never {@code null} * @param methodName the name of the method to find; never {@code null} * or empty * @param parameterTypes the types of parameters accepted by the method, * if any; never {@code null} * @return the {@code Method} found; never {@code null} * @throws JUnitException if no method is found * * @since 1.7 * @see #findMethod(Class, String, Class...) */ @API(status = STABLE, since = "1.7") public static Method getRequiredMethod(Class clazz, String methodName, Class... parameterTypes) { return ReflectionUtils.findMethod(clazz, methodName, parameterTypes).orElseThrow( () -> new JUnitException(format("Could not find method [%s] in class [%s]", methodName, clazz.getName()))); } /** * Find all {@linkplain Method methods} of the supplied class or interface * that match the specified {@code predicate}, using top-down search semantics * within the type hierarchy. * *

The results will not contain instance methods that are overridden * or {@code static} methods that are hidden. * * @param clazz the class or interface in which to find the methods; never {@code null} * @param predicate the method filter; never {@code null} * @return an immutable list of all such methods found; never {@code null} * @see HierarchyTraversalMode#TOP_DOWN * @see #findMethods(Class, Predicate, HierarchyTraversalMode) */ public static List findMethods(Class clazz, Predicate predicate) { return findMethods(clazz, predicate, TOP_DOWN); } /** * @see org.junit.platform.commons.support.ReflectionSupport#findMethods(Class, Predicate, org.junit.platform.commons.support.HierarchyTraversalMode) */ public static List findMethods(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { return streamMethods(clazz, predicate, traversalMode).collect(toUnmodifiableList()); } /** * @since 1.10 * @see org.junit.platform.commons.support.ReflectionSupport#streamMethods(Class, Predicate, org.junit.platform.commons.support.HierarchyTraversalMode) */ public static Stream streamMethods(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); // @formatter:off return findAllMethodsInHierarchy(clazz, traversalMode).stream() .filter(predicate) .distinct(); // @formatter:on } /** * Find all non-synthetic methods in the superclass and interface hierarchy, * excluding Object. */ private static List findAllMethodsInHierarchy(Class clazz, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); // @formatter:off List localMethods = getDeclaredMethods(clazz, traversalMode).stream() .filter(method -> !method.isSynthetic()) .collect(toList()); List superclassMethods = getSuperclassMethods(clazz, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localMethods)) .collect(toList()); List interfaceMethods = getInterfaceMethods(clazz, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localMethods)) .collect(toList()); // @formatter:on List methods = new ArrayList<>(); if (traversalMode == TOP_DOWN) { methods.addAll(superclassMethods); methods.addAll(interfaceMethods); } methods.addAll(localMethods); if (traversalMode == BOTTOM_UP) { methods.addAll(interfaceMethods); methods.addAll(superclassMethods); } return methods; } /** * Custom alternative to {@link Class#getFields()} that sorts the fields * and converts them to a mutable list. */ private static List getFields(Class clazz) { return toSortedMutableList(clazz.getFields()); } /** * Custom alternative to {@link Class#getDeclaredFields()} that sorts the * fields and converts them to a mutable list. */ private static List getDeclaredFields(Class clazz) { return toSortedMutableList(clazz.getDeclaredFields()); } /** * Custom alternative to {@link Class#getMethods()} that sorts the methods * and converts them to a mutable list. */ private static List getMethods(Class clazz) { return toSortedMutableList(clazz.getMethods()); } /** * Custom alternative to {@link Class#getDeclaredMethods()} that sorts the * methods and converts them to a mutable list. * *

In addition, the list returned by this method includes interface * default methods which are either prepended or appended to the list of * declared methods depending on the supplied traversal mode. */ private static List getDeclaredMethods(Class clazz, HierarchyTraversalMode traversalMode) { // Note: getDefaultMethods() already sorts the methods, List defaultMethods = getDefaultMethods(clazz); List declaredMethods = toSortedMutableList(clazz.getDeclaredMethods()); // Take the traversal mode into account in order to retain the inherited // nature of interface default methods. if (traversalMode == BOTTOM_UP) { declaredMethods.addAll(defaultMethods); return declaredMethods; } else { defaultMethods.addAll(declaredMethods); return defaultMethods; } } /** * Get a sorted, mutable list of all default methods present in interfaces * implemented by the supplied class which are also visible within * the supplied class. * * @see Method Visibility * in the Java Language Specification */ private static List getDefaultMethods(Class clazz) { // @formatter:off // Visible default methods are interface default methods that have not // been overridden. List visibleDefaultMethods = Arrays.stream(clazz.getMethods()) .filter(Method::isDefault) .collect(toCollection(ArrayList::new)); if (visibleDefaultMethods.isEmpty()) { return visibleDefaultMethods; } return Arrays.stream(clazz.getInterfaces()) .map(ReflectionUtils::getMethods) .flatMap(List::stream) .filter(visibleDefaultMethods::contains) .collect(toCollection(ArrayList::new)); // @formatter:on } private static List toSortedMutableList(Field[] fields) { // @formatter:off return Arrays.stream(fields) .sorted(ReflectionUtils::defaultFieldSorter) // Use toCollection() instead of toList() to ensure list is mutable. .collect(toCollection(ArrayList::new)); // @formatter:on } private static List toSortedMutableList(Method[] methods) { // @formatter:off return Arrays.stream(methods) .sorted(ReflectionUtils::defaultMethodSorter) // Use toCollection() instead of toList() to ensure list is mutable. .collect(toCollection(ArrayList::new)); // @formatter:on } /** * Field comparator inspired by JUnit 4's {@code org.junit.internal.MethodSorter} * implementation. */ private static int defaultFieldSorter(Field field1, Field field2) { return Integer.compare(field1.getName().hashCode(), field2.getName().hashCode()); } /** * Method comparator based upon JUnit 4's {@code org.junit.internal.MethodSorter} * implementation. */ private static int defaultMethodSorter(Method method1, Method method2) { String name1 = method1.getName(); String name2 = method2.getName(); int comparison = Integer.compare(name1.hashCode(), name2.hashCode()); if (comparison == 0) { comparison = name1.compareTo(name2); if (comparison == 0) { comparison = method1.toString().compareTo(method2.toString()); } } return comparison; } private static List getInterfaceMethods(Class clazz, HierarchyTraversalMode traversalMode) { List allInterfaceMethods = new ArrayList<>(); for (Class ifc : clazz.getInterfaces()) { // @formatter:off List localInterfaceMethods = getMethods(ifc).stream() .filter(m -> !isAbstract(m)) .collect(toList()); List superinterfaceMethods = getInterfaceMethods(ifc, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localInterfaceMethods)) .collect(toList()); // @formatter:on if (traversalMode == TOP_DOWN) { allInterfaceMethods.addAll(superinterfaceMethods); } allInterfaceMethods.addAll(localInterfaceMethods); if (traversalMode == BOTTOM_UP) { allInterfaceMethods.addAll(superinterfaceMethods); } } return allInterfaceMethods; } private static List getInterfaceFields(Class clazz, HierarchyTraversalMode traversalMode) { List allInterfaceFields = new ArrayList<>(); for (Class ifc : clazz.getInterfaces()) { List localInterfaceFields = getFields(ifc); // @formatter:off List superinterfaceFields = getInterfaceFields(ifc, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localInterfaceFields)) .collect(toList()); // @formatter:on if (traversalMode == TOP_DOWN) { allInterfaceFields.addAll(superinterfaceFields); } allInterfaceFields.addAll(localInterfaceFields); if (traversalMode == BOTTOM_UP) { allInterfaceFields.addAll(superinterfaceFields); } } return allInterfaceFields; } private static List getSuperclassFields(Class clazz, HierarchyTraversalMode traversalMode) { Class superclass = clazz.getSuperclass(); if (!isSearchable(superclass)) { return Collections.emptyList(); } return findAllFieldsInHierarchy(superclass, traversalMode); } private static boolean isFieldShadowedByLocalFields(Field field, List localFields) { return localFields.stream().anyMatch(local -> local.getName().equals(field.getName())); } private static List getSuperclassMethods(Class clazz, HierarchyTraversalMode traversalMode) { Class superclass = clazz.getSuperclass(); if (!isSearchable(superclass)) { return Collections.emptyList(); } return findAllMethodsInHierarchy(superclass, traversalMode); } private static boolean isMethodShadowedByLocalMethods(Method method, List localMethods) { return localMethods.stream().anyMatch(local -> isMethodShadowedBy(method, local)); } private static boolean isMethodShadowedBy(Method upper, Method lower) { return hasCompatibleSignature(upper, lower.getName(), lower.getParameterTypes()); } /** * Determine if the supplied candidate method (typically a method higher in * the type hierarchy) has a signature that is compatible with a method that * has the supplied name and parameter types, taking method sub-signatures * and generics into account. */ private static boolean hasCompatibleSignature(Method candidate, String methodName, Class[] parameterTypes) { if (!methodName.equals(candidate.getName())) { return false; } if (parameterTypes.length != candidate.getParameterCount()) { return false; } // trivial case: parameter types exactly match if (Arrays.equals(parameterTypes, candidate.getParameterTypes())) { return true; } // param count is equal, but types do not match exactly: check for method sub-signatures // https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2 for (int i = 0; i < parameterTypes.length; i++) { Class lowerType = parameterTypes[i]; Class upperType = candidate.getParameterTypes()[i]; if (!upperType.isAssignableFrom(lowerType)) { return false; } } // lower is sub-signature of upper: check for generics in upper method if (isGeneric(candidate)) { return true; } return false; } static boolean isGeneric(Method method) { return isGeneric(method.getGenericReturnType()) || Arrays.stream(method.getGenericParameterTypes()).anyMatch(ReflectionUtils::isGeneric); } private static boolean isGeneric(Type type) { return type instanceof TypeVariable || type instanceof GenericArrayType; } @SuppressWarnings("deprecation") // "AccessibleObject.isAccessible()" is deprecated in Java 9 public static T makeAccessible(T object) { if (!object.isAccessible()) { object.setAccessible(true); } return object; } /** * Return all classes and interfaces that can be used as assignment types * for instances of the specified {@link Class}, including itself. * * @param clazz the {@code Class} to look up * @see Class#isAssignableFrom */ public static Set> getAllAssignmentCompatibleClasses(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); Set> result = new LinkedHashSet<>(); getAllAssignmentCompatibleClasses(clazz, result); return result; } private static void getAllAssignmentCompatibleClasses(Class clazz, Set> result) { for (Class current = clazz; current != null; current = current.getSuperclass()) { result.add(current); for (Class interfaceClass : current.getInterfaces()) { if (!result.contains(interfaceClass)) { getAllAssignmentCompatibleClasses(interfaceClass, result); } } } } /** * Determine if the supplied class is searchable: is non-null and is * not equal to the class reference for {@code java.lang.Object}. * *

This method is often used to determine if a superclass should be * searched but may be applicable for other use cases as well. * @since 1.6 */ private static boolean isSearchable(Class clazz) { return (clazz != null && clazz != Object.class); } /** * Get the underlying cause of the supplied {@link Throwable}. * *

If the supplied {@code Throwable} is an instance of * {@link InvocationTargetException}, this method will be invoked * recursively with the underlying * {@linkplain InvocationTargetException#getTargetException() target * exception}; otherwise, this method returns the supplied {@code Throwable}. */ private static Throwable getUnderlyingCause(Throwable t) { if (t instanceof InvocationTargetException) { return getUnderlyingCause(((InvocationTargetException) t).getTargetException()); } return t; } } RuntimeUtils.java000066400000000000000000000044251455764576500337400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.List; import java.util.Optional; import org.apiguardian.api.API; /** * Collection of utilities for working with {@link Runtime}, * {@link java.lang.management.RuntimeMXBean}, etc. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.6 */ @API(status = INTERNAL, since = "1.6") public final class RuntimeUtils { private RuntimeUtils() { /* no-op */ } /** * Try to determine whether the VM was started in debug mode or not. */ public static boolean isDebugMode() { return getInputArguments() // .map(args -> args.stream().anyMatch( arg -> arg.startsWith("-agentlib:jdwp") || arg.startsWith("-Xrunjdwp"))) // .orElse(false); } /** * Try to get the input arguments the VM was started with. */ static Optional> getInputArguments() { Optional> managementFactoryClass = ReflectionUtils.tryToLoadClass( "java.lang.management.ManagementFactory").toOptional(); if (!managementFactoryClass.isPresent()) { return Optional.empty(); } // Can't use "java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments()" // directly as module "java.management" might not be available and/or the current platform // doesn't support the Java Management Extensions (JMX) API (like Android?). // See https://github.com/junit-team/junit4/pull/1187 try { Object bean = managementFactoryClass.get().getMethod("getRuntimeMXBean").invoke(null); Class mx = ReflectionUtils.tryToLoadClass("java.lang.management.RuntimeMXBean").get(); @SuppressWarnings("unchecked") List args = (List) mx.getMethod("getInputArguments").invoke(bean); return Optional.of(args); } catch (Exception e) { return Optional.empty(); } } } junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java000066400000000000000000000212431455764576500336370ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; import java.util.regex.Pattern; import org.apiguardian.api.API; /** * Collection of utilities for working with {@link String Strings}, * {@link CharSequence CharSequences}, etc. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public final class StringUtils { private static final Pattern ISO_CONTROL_PATTERN = compileIsoControlPattern(); private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s"); /** * Guard against "IllegalArgumentException: Unsupported flags: 256" errors. * @see #1800 */ static Pattern compileIsoControlPattern() { // https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#posix try { // All of the characters that Unicode refers to as 'control characters' return Pattern.compile("\\p{Cntrl}", UNICODE_CHARACTER_CLASS); } catch (IllegalArgumentException e) { // Fall-back to ASCII control characters only: [\x00-\x1F\x7F] return Pattern.compile("\\p{Cntrl}"); } } private StringUtils() { /* no-op */ } /** * Determine if the supplied {@link String} is blank (i.e., * {@code null} or consisting only of whitespace characters). * * @param str the string to check; may be {@code null} * @return {@code true} if the string is blank * @see #isNotBlank(String) */ public static boolean isBlank(String str) { return (str == null || str.trim().isEmpty()); } /** * Determine if the supplied {@link String} is not {@linkplain #isBlank * blank}. * * @param str the string to check; may be {@code null} * @return {@code true} if the string is not blank * @see #isBlank(String) */ public static boolean isNotBlank(String str) { return !isBlank(str); } /** * Determine if the supplied {@link String} contains any whitespace characters. * * @param str the string to check; may be {@code null} * @return {@code true} if the string contains whitespace * @see #containsIsoControlCharacter(String) * @see Character#isWhitespace(int) */ public static boolean containsWhitespace(String str) { return str != null && str.codePoints().anyMatch(Character::isWhitespace); } /** * Determine if the supplied {@link String} does not contain any whitespace * characters. * * @param str the string to check; may be {@code null} * @return {@code true} if the string does not contain whitespace * @see #containsWhitespace(String) * @see #containsIsoControlCharacter(String) * @see Character#isWhitespace(int) */ public static boolean doesNotContainWhitespace(String str) { return !containsWhitespace(str); } /** * Determine if the supplied {@link String} contains any ISO control characters. * * @param str the string to check; may be {@code null} * @return {@code true} if the string contains an ISO control character * @see #containsWhitespace(String) * @see Character#isISOControl(int) */ public static boolean containsIsoControlCharacter(String str) { return str != null && str.codePoints().anyMatch(Character::isISOControl); } /** * Determine if the supplied {@link String} does not contain any ISO control * characters. * * @param str the string to check; may be {@code null} * @return {@code true} if the string does not contain an ISO control character * @see #containsIsoControlCharacter(String) * @see #containsWhitespace(String) * @see Character#isISOControl(int) */ public static boolean doesNotContainIsoControlCharacter(String str) { return !containsIsoControlCharacter(str); } /** * Convert the supplied {@code Object} to a {@code String} using the * following algorithm. * *

    *
  • If the supplied object is {@code null}, this method returns {@code "null"}.
  • *
  • If the supplied object is a primitive array, the appropriate * {@code Arrays#toString(...)} variant will be used to convert it to a String.
  • *
  • If the supplied object is an object array, {@code Arrays#deepToString(Object[])} * will be used to convert it to a String.
  • *
  • Otherwise, {@code toString()} will be invoked on the object. If the * result is non-null, that result will be returned. If the result is * {@code null}, {@code "null"} will be returned.
  • *
  • If any of the above results in an exception, this method delegates to * {@link #defaultToString(Object)}
  • *
* * @param obj the object to convert to a String; may be {@code null} * @return a String representation of the supplied object; never {@code null} * @see Arrays#deepToString(Object[]) * @see ClassUtils#nullSafeToString(Class...) */ public static String nullSafeToString(Object obj) { if (obj == null) { return "null"; } try { if (obj.getClass().isArray()) { if (obj.getClass().getComponentType().isPrimitive()) { if (obj instanceof boolean[]) { return Arrays.toString((boolean[]) obj); } if (obj instanceof char[]) { return Arrays.toString((char[]) obj); } if (obj instanceof short[]) { return Arrays.toString((short[]) obj); } if (obj instanceof byte[]) { return Arrays.toString((byte[]) obj); } if (obj instanceof int[]) { return Arrays.toString((int[]) obj); } if (obj instanceof long[]) { return Arrays.toString((long[]) obj); } if (obj instanceof float[]) { return Arrays.toString((float[]) obj); } if (obj instanceof double[]) { return Arrays.toString((double[]) obj); } } return Arrays.deepToString((Object[]) obj); } // else String result = obj.toString(); return result != null ? result : "null"; } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); return defaultToString(obj); } } /** * Convert the supplied {@code Object} to a default {@code String} * representation using the following algorithm. * *
    *
  • If the supplied object is {@code null}, this method returns {@code "null"}.
  • *
  • Otherwise, the String returned by this method will be generated analogous * to the default implementation of {@link Object#toString()} by using the supplied * object's class name and hash code as follows: * {@code obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj))}
  • *
* * @param obj the object to convert to a String; may be {@code null} * @return the default String representation of the supplied object; never {@code null} * @see #nullSafeToString(Object) * @see ClassUtils#nullSafeToString(Class...) */ public static String defaultToString(Object obj) { if (obj == null) { return "null"; } return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); } /** * Replace all ISO control characters in the supplied {@link String}. * * @param str the string in which to perform the replacement; may be {@code null} * @param replacement the replacement string; never {@code null} * @return the supplied string with all control characters replaced, or * {@code null} if the supplied string was {@code null} * @since 1.4 */ @API(status = INTERNAL, since = "1.4") public static String replaceIsoControlCharacters(String str, String replacement) { Preconditions.notNull(replacement, "replacement must not be null"); return str == null ? null : ISO_CONTROL_PATTERN.matcher(str).replaceAll(replacement); } /** * Replace all whitespace characters in the supplied {@link String}. * * @param str the string in which to perform the replacement; may be {@code null} * @param replacement the replacement string; never {@code null} * @return the supplied string with all whitespace characters replaced, or * {@code null} if the supplied string was {@code null} * @since 1.4 */ @API(status = INTERNAL, since = "1.4") public static String replaceWhitespaceCharacters(String str, String replacement) { Preconditions.notNull(replacement, "replacement must not be null"); return str == null ? null : WHITESPACE_PATTERN.matcher(str).replaceAll(replacement); } } ToStringBuilder.java000066400000000000000000000035621455764576500343550ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.lang.String.join; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ArrayList; import java.util.List; import org.apiguardian.api.API; /** * Simple builder for generating strings in custom implementations of * {@link Object#toString toString()}. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public class ToStringBuilder { private final String typeName; private final List values = new ArrayList<>(); public ToStringBuilder(Object obj) { this(Preconditions.notNull(obj, "Object must not be null").getClass().getSimpleName()); } public ToStringBuilder(Class type) { this(Preconditions.notNull(type, "Class must not be null").getSimpleName()); } @API(status = INTERNAL, since = "1.7") public ToStringBuilder(String typeName) { this.typeName = Preconditions.notNull(typeName, "Type name must not be null"); } public ToStringBuilder append(String name, Object value) { Preconditions.notBlank(name, "Name must not be null or blank"); this.values.add(name + " = " + toString(value)); return this; } private String toString(Object obj) { return (obj instanceof CharSequence) ? ("'" + obj + "'") : StringUtils.nullSafeToString(obj); } @Override public String toString() { return this.typeName + " [" + join(", ", this.values) + "]"; } } UnrecoverableExceptions.java000066400000000000000000000027351455764576500361340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; /** * Internal utilities for working with unrecoverable exceptions. * *

Unrecoverable exceptions are those that should always terminate * test plan execution immediately. * *

Currently Unrecoverable Exceptions

*
    *
  • {@link OutOfMemoryError}
  • *
* *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.7 */ @API(status = INTERNAL, since = "1.7") public final class UnrecoverableExceptions { private UnrecoverableExceptions() { /* no-op */ } /** * Rethrow the supplied {@link Throwable exception} if it is * unrecoverable. * *

If the supplied {@code exception} is not unrecoverable, this * method does nothing. */ public static void rethrowIfUnrecoverable(Throwable exception) { if (exception instanceof OutOfMemoryError) { ExceptionUtils.throwAsUncheckedException(exception); } } } package-info.java000066400000000000000000000004531455764576500336150ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java/org/junit/platform/commons/util/** * Internal common utilities for JUnit. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! */ package org.junit.platform.commons.util; junit5-r5.10.2/junit-platform-commons/src/main/java9/000077500000000000000000000000001455764576500224005ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/000077500000000000000000000000001455764576500231675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/junit/000077500000000000000000000000001455764576500243205ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/junit/platform/000077500000000000000000000000001455764576500261445ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/junit/platform/commons/000077500000000000000000000000001455764576500276175ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/000077500000000000000000000000001455764576500305745ustar00rootroot00000000000000ModuleUtils.java000066400000000000000000000160611455764576500336320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.IOException; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; /** * Collection of utilities for working with {@code java.lang.Module} * and friends. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.1 */ @API(status = INTERNAL, since = "1.1") public class ModuleUtils { private static final Logger logger = LoggerFactory.getLogger(ModuleUtils.class); /** * Find all non-system boot modules names. * * @return a set of all such module names; never {@code null} but * potentially empty */ public static Set findAllNonSystemBootModuleNames() { // @formatter:off Set systemModules = ModuleFinder.ofSystem().findAll().stream() .map(reference -> reference.descriptor().name()) .collect(toSet()); return streamResolvedModules(name -> !systemModules.contains(name)) .map(ResolvedModule::name) .collect(toCollection(LinkedHashSet::new)); // @formatter:on } /** * Java 9+ runtime supports the Java Platform Module System. * * @return {@code true} */ public static boolean isJavaPlatformModuleSystemAvailable() { return true; } public static Optional getModuleName(Class type) { Preconditions.notNull(type, "Class type must not be null"); return Optional.ofNullable(type.getModule().getName()); } public static Optional getModuleVersion(Class type) { Preconditions.notNull(type, "Class type must not be null"); Module module = type.getModule(); return module.isNamed() ? module.getDescriptor().rawVersion() : Optional.empty(); } /** * Find all classes for the given module name. * * @param moduleName the name of the module to scan; never {@code null} or * empty * @param filter the class filter to apply; never {@code null} * @return an immutable list of all such classes found; never {@code null} * but potentially empty */ public static List> findAllClassesInModule(String moduleName, ClassFilter filter) { Preconditions.notBlank(moduleName, "Module name must not be null or empty"); Preconditions.notNull(filter, "Class filter must not be null"); logger.debug(() -> "Looking for classes in module: " + moduleName); // @formatter:off Set moduleReferences = streamResolvedModules(isEqual(moduleName)) .map(ResolvedModule::reference) .collect(toSet()); // @formatter:on return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader()); } /** * Stream resolved modules from current (or boot) module layer. */ private static Stream streamResolvedModules(Predicate moduleNamePredicate) { Module module = ModuleUtils.class.getModule(); ModuleLayer layer = module.getLayer(); if (layer == null) { logger.config(() -> ModuleUtils.class + " is a member of " + module + " - using boot layer returned by ModuleLayer.boot() as fall-back."); layer = ModuleLayer.boot(); } return streamResolvedModules(moduleNamePredicate, layer); } /** * Stream resolved modules from the supplied layer. */ private static Stream streamResolvedModules(Predicate moduleNamePredicate, ModuleLayer layer) { logger.debug(() -> "Streaming modules for layer @" + System.identityHashCode(layer) + ": " + layer); Configuration configuration = layer.configuration(); logger.debug(() -> "Module layer configuration: " + configuration); Stream stream = configuration.modules().stream(); return stream.filter(module -> moduleNamePredicate.test(module.name())); } /** * Scan for classes using the supplied set of module references, class * filter, and loader. */ private static List> scan(Set references, ClassFilter filter, ClassLoader loader) { logger.debug(() -> "Scanning " + references.size() + " module references: " + references); ModuleReferenceScanner scanner = new ModuleReferenceScanner(filter, loader); List> classes = new ArrayList<>(); for (ModuleReference reference : references) { classes.addAll(scanner.scan(reference)); } logger.debug(() -> "Found " + classes.size() + " classes: " + classes); return Collections.unmodifiableList(classes); } /** * {@link ModuleReference} scanner. */ static class ModuleReferenceScanner { private final ClassFilter classFilter; private final ClassLoader classLoader; ModuleReferenceScanner(ClassFilter classFilter, ClassLoader classLoader) { this.classFilter = classFilter; this.classLoader = classLoader; } /** * Scan module reference for classes that potentially contain testable methods. */ List> scan(ModuleReference reference) { try (ModuleReader reader = reference.open()) { try (Stream names = reader.list()) { // @formatter:off return names.filter(name -> name.endsWith(".class")) .map(this::className) .filter(name -> !name.equals("module-info")) .filter(classFilter::match) .map(this::loadClassUnchecked) .filter(classFilter::match) .collect(Collectors.toList()); // @formatter:on } } catch (IOException e) { throw new JUnitException("Failed to read contents of " + reference + ".", e); } } /** * Convert resource name to binary class name. */ private String className(String resourceName) { resourceName = resourceName.substring(0, resourceName.length() - 6); // 6 = ".class".length() resourceName = resourceName.replace('/', '.'); return resourceName; } /** * Load class by its binary name. * * @see ClassLoader#loadClass(String) */ private Class loadClassUnchecked(String binaryName) { try { return classLoader.loadClass(binaryName); } catch (ClassNotFoundException e) { throw new JUnitException("Failed to load class with name '" + binaryName + "'.", e); } } } } junit5-r5.10.2/junit-platform-commons/src/module/000077500000000000000000000000001455764576500217275ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/module/org.junit.platform.commons/000077500000000000000000000000001455764576500271435ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java000066400000000000000000000032631455764576500322300ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Common APIs and support utilities for the JUnit Platform. * * @since 1.0 */ module org.junit.platform.commons { requires java.logging; requires java.management; // needed by RuntimeUtils to determine input arguments requires static transitive org.apiguardian.api; exports org.junit.platform.commons; exports org.junit.platform.commons.annotation; exports org.junit.platform.commons.function; exports org.junit.platform.commons.logging to org.junit.jupiter.api, org.junit.jupiter.engine, org.junit.jupiter.migrationsupport, org.junit.jupiter.params, org.junit.platform.console, org.junit.platform.engine, org.junit.platform.launcher, org.junit.platform.reporting, org.junit.platform.runner, org.junit.platform.suite.api, org.junit.platform.suite.engine, org.junit.platform.testkit, org.junit.vintage.engine; exports org.junit.platform.commons.support; exports org.junit.platform.commons.util to org.junit.jupiter.api, org.junit.jupiter.engine, org.junit.jupiter.migrationsupport, org.junit.jupiter.params, org.junit.platform.console, org.junit.platform.engine, org.junit.platform.launcher, org.junit.platform.reporting, org.junit.platform.runner, org.junit.platform.suite.api, org.junit.platform.suite.commons, org.junit.platform.suite.engine, org.junit.platform.testkit, org.junit.vintage.engine; } junit5-r5.10.2/junit-platform-commons/src/testFixtures/000077500000000000000000000000001455764576500231535ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/000077500000000000000000000000001455764576500240745ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/000077500000000000000000000000001455764576500246635ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500260145ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/platform/000077500000000000000000000000001455764576500276405ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/000077500000000000000000000000001455764576500313135ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/000077500000000000000000000000001455764576500322725ustar00rootroot00000000000000ConcurrencyTestingUtils.java000066400000000000000000000040371455764576500377330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.test; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ConcurrencyTestingUtils { public static void executeConcurrently(int threads, Runnable action) throws Exception { executeConcurrently(threads, () -> { action.run(); return null; }); } public static List executeConcurrently(int threads, Callable action) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(threads); try { CountDownLatch latch = new CountDownLatch(threads); List> futures = new ArrayList<>(); for (int i = 0; i < threads; i++) { futures.add(CompletableFuture.supplyAsync(() -> { try { latch.countDown(); latch.await(); return action.call(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new CompletionException(e); } catch (Exception e) { throw new CompletionException("Action failed", e); } }, executorService)); } List list = new ArrayList<>(); for (CompletableFuture future : futures) { list.add(future.get(5, SECONDS)); } return list; } finally { executorService.shutdownNow(); var terminated = executorService.awaitTermination(5, SECONDS); if (!terminated) { //noinspection ThrowFromFinallyBlock throw new AssertionError("ExecutorService did not cleanly shut down"); } } } } TestClassLoader.java000066400000000000000000000062761455764576500361250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.test; import java.lang.StackWalker.Option; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import org.junit.platform.commons.util.ClassLoaderUtils; /** * Test {@link ClassLoader} which accepts a class name {@link Predicate} to * filter classes that should be loaded by this {@code ClassLoader} instead of * the {@linkplain ClassLoaderUtils#getDefaultClassLoader() default ClassLoader}. * *

This class loader is only suitable for specific testing scenarios, where * you need to load particular classes from a different class loader. * * @since 1.10 */ public class TestClassLoader extends URLClassLoader { private static final StackWalker stackWalker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); static { ClassLoader.registerAsParallelCapable(); } /** * Create a {@link TestClassLoader} that filters the provided classes. * * @see #forClasses(List) * @see #forClassNamePrefix(String) */ public static TestClassLoader forClasses(Class... classes) { Predicate classNameFilter = name -> Arrays.stream(classes).map(Class::getName).anyMatch(name::equals); return new TestClassLoader(getCodeSourceUrl(stackWalker.getCallerClass()), classNameFilter); } /** * Create a {@link TestClassLoader} that filters the provided classes. * * @see #forClasses(Class...) * @see #forClassNamePrefix(String) */ public static TestClassLoader forClasses(List> classes) { Predicate classNameFilter = name -> classes.stream().map(Class::getName).anyMatch(name::equals); return new TestClassLoader(getCodeSourceUrl(stackWalker.getCallerClass()), classNameFilter); } /** * Create a {@link TestClassLoader} that filters classes whose fully * qualified names start with the provided prefix. * * @see #forClasses(Class...) * @see #forClasses(List) */ public static TestClassLoader forClassNamePrefix(String prefix) { return new TestClassLoader(getCodeSourceUrl(stackWalker.getCallerClass()), name -> name.startsWith(prefix)); } private final Predicate classNameFilter; private TestClassLoader(URL codeSourceUrl, Predicate classNameFilter) { super(new URL[] { codeSourceUrl }, ClassLoaderUtils.getDefaultClassLoader()); this.classNameFilter = classNameFilter; } @Override public Class loadClass(String name) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { Class clazz = findLoadedClass(name); if (clazz != null) { return clazz; } return this.classNameFilter.test(name) ? findClass(name) : super.loadClass(name); } } /** * Get the {@link CodeSource} {@link URL} of the supplied class. */ private static URL getCodeSourceUrl(Class clazz) { return clazz.getProtectionDomain().getCodeSource().getLocation(); } } junit5-r5.10.2/junit-platform-console-standalone/000077500000000000000000000000001455764576500217705ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts000066400000000000000000000057671455764576500325300ustar00rootroot00000000000000import junitbuild.java.WriteArtifactsFile plugins { id("junitbuild.java-library-conventions") id("junitbuild.shadow-conventions") } description = "JUnit Platform Console Standalone" dependencies { shadowed(projects.junitPlatformReporting) shadowed(projects.junitPlatformConsole) shadowed(projects.junitPlatformSuite) shadowed(projects.junitJupiterEngine) shadowed(projects.junitJupiterParams) shadowed(projects.junitVintageEngine) shadowed(libs.apiguardian) { because("downstream projects need it to avoid compiler warnings") } } val jupiterVersion = rootProject.version val vintageVersion: String by project tasks { jar { manifest { attributes("Main-Class" to "org.junit.platform.console.ConsoleLauncher") } } val shadowedArtifactsFile by registering(WriteArtifactsFile::class) { from(configurations.shadowed) outputFile = layout.buildDirectory.file("shadowed-artifacts") } shadowJar { // https://github.com/junit-team/junit5/issues/2557 // exclude compiled module declarations from any source (e.g. /*, /META-INF/versions/N/*) exclude("**/module-info.class") // https://github.com/junit-team/junit5/issues/761 // prevent duplicates, add 3rd-party licenses explicitly exclude("META-INF/LICENSE*.md") from(project.projects.junitPlatformConsole.dependencyProject.projectDir) { include("LICENSE-picocli.md") into("META-INF") } from(project.projects.junitJupiterParams.dependencyProject.projectDir) { include("LICENSE-univocity-parsers.md") into("META-INF") } from(shadowedArtifactsFile) { into("META-INF") } bundle { val importAPIGuardian: String by extra bnd(""" # Customize the imports because this is an aggregate jar Import-Package: \ $importAPIGuardian,\ kotlin.*;resolution:="optional",\ * # Disable the APIGuardian plugin since everything was already # processed, again because this is an aggregate jar -export-apiguardian: """) } mergeServiceFiles() manifest.apply { inheritFrom(jar.get().manifest) attributes(mapOf( "Specification-Title" to project.name, "Implementation-Title" to project.name, // Generate test engine version information in single shared manifest file. // Pattern of key and value: `"Engine-Version-{YourTestEngine#getId()}": "47.11"` "Engine-Version-junit-jupiter" to jupiterVersion, "Engine-Version-junit-vintage" to vintageVersion, // Version-aware binaries are already included - set Multi-Release flag here. // See https://openjdk.java.net/jeps/238 for details // Note: the "jar --update ... --release X" command does not work with the // shadowed JAR as it contains nested classes that do not comply with multi-release jars. "Multi-Release" to true )) } } // This jar contains some Java 9 code // (org.junit.platform.console.ConsoleLauncherToolProvider which implements // java.util.spi.ToolProvider which is @since 9). // So in order to resolve this, it can only run on Java 9 osgiProperties { property("-runee", "JavaSE-9") } } junit5-r5.10.2/junit-platform-console/000077500000000000000000000000001455764576500176425ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/LICENSE-picocli.md000066400000000000000000000243621455764576500226750ustar00rootroot00000000000000Apache License ============== _Version 2.0, January 2004_ _<>_ ### Terms and Conditions for use, reproduction, and distribution #### 1. Definitions “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. #### 2. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. #### 3. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. #### 4. Redistribution You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: * **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and * **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and * **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. #### 5. Submission of Contributions Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. #### 6. Trademarks This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. #### 7. Disclaimer of Warranty Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) 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. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. #### 8. Limitation of Liability In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. #### 9. Accepting Warranty or Additional Liability While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. _END OF TERMS AND CONDITIONS_ ### APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets `[]` replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed 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 https://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. junit5-r5.10.2/junit-platform-console/junit-platform-console.gradle.kts000066400000000000000000000043551455764576500262440ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") id("junitbuild.shadow-conventions") id("junitbuild.java-multi-release-sources") id("junitbuild.java-repackage-jars") } description = "JUnit Platform Console" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformReporting) compileOnlyApi(libs.apiguardian) compileOnly(libs.openTestReporting.events) shadowed(libs.picocli) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks { compileModule { options.compilerArgs.addAll(listOf( "--add-modules", "org.opentest4j.reporting.events", "--add-reads", "${project.projects.junitPlatformReporting.dependencyProject.javaModuleName}=org.opentest4j.reporting.events", "--add-modules", "info.picocli", "--add-reads", "${javaModuleName}=info.picocli" )) } shadowJar { val release17ClassesDir = sourceSets.mainRelease17.get().output.classesDirs.singleFile inputs.dir(release17ClassesDir).withPathSensitivity(PathSensitivity.RELATIVE) exclude("META-INF/versions/9/module-info.class") relocate("picocli", "org.junit.platform.console.shadow.picocli") from(projectDir) { include("LICENSE-picocli.md") into("META-INF") } from(sourceSets.mainRelease9.get().output.classesDirs) doLast(objects.newInstance(junitbuild.java.ExecJarAction::class).apply { javaLauncher = project.javaToolchains.launcherFor(java.toolchain) args.addAll( "--update", "--file", archiveFile.get().asFile.absolutePath, "--main-class", "org.junit.platform.console.ConsoleLauncher", "--release", "17", "-C", release17ClassesDir.absolutePath, "." ) }) } codeCoverageClassesJar { exclude("org/junit/platform/console/options/ConsoleUtils.class") } jar { manifest { attributes("Main-Class" to "org.junit.platform.console.ConsoleLauncher") } } // This jar contains some Java 9 code // (org.junit.platform.console.ConsoleLauncherToolProvider which implements // java.util.spi.ToolProvider which is @since 9). // So in order to resolve this, it can only run on Java 9 osgiProperties { property("-runee", "JavaSE-9") } } eclipse { classpath { sourceSets -= project.sourceSets.mainRelease9.get() sourceSets -= project.sourceSets.mainRelease17.get() } } junit5-r5.10.2/junit-platform-console/src/000077500000000000000000000000001455764576500204315ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/000077500000000000000000000000001455764576500213555ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/000077500000000000000000000000001455764576500222765ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/000077500000000000000000000000001455764576500230655ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/000077500000000000000000000000001455764576500242165ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500260425ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/000077500000000000000000000000001455764576500275045ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/ConsoleLauncher.java000066400000000000000000000036221455764576500334360ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.PrintWriter; import org.apiguardian.api.API; import org.junit.platform.console.options.CommandFacade; import org.junit.platform.console.options.CommandResult; import org.junit.platform.console.tasks.ConsoleTestExecutor; /** * The {@code ConsoleLauncher} is a stand-alone application for launching the * JUnit Platform from the console. * * @since 1.0 */ @API(status = MAINTAINED, since = "1.0") public class ConsoleLauncher { public static void main(String... args) { PrintWriter out = new PrintWriter(System.out); PrintWriter err = new PrintWriter(System.err); CommandResult result = run(out, err, args); System.exit(result.getExitCode()); } @API(status = INTERNAL, since = "1.0") public static CommandResult run(PrintWriter out, PrintWriter err, String... args) { ConsoleLauncher consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, out, err); return consoleLauncher.run(args); } private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; private final PrintWriter out; private final PrintWriter err; ConsoleLauncher(ConsoleTestExecutor.Factory consoleTestExecutorFactory, PrintWriter out, PrintWriter err) { this.consoleTestExecutorFactory = consoleTestExecutorFactory; this.out = out; this.err = err; } CommandResult run(String... args) { try { return new CommandFacade(consoleTestExecutorFactory).run(out, err, args); } finally { out.flush(); err.flush(); } } } junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/000077500000000000000000000000001455764576500311775ustar00rootroot00000000000000BaseCommand.java000066400000000000000000000055731455764576500341460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.io.PrintWriter; import java.util.concurrent.Callable; import org.junit.platform.commons.PreconditionViolationException; import picocli.CommandLine; import picocli.CommandLine.Mixin; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; import picocli.CommandLine.ParameterException; import picocli.CommandLine.Spec; abstract class BaseCommand implements Callable { @Spec CommandSpec commandSpec; @Mixin OutputOptionsMixin outputOptions; @SuppressWarnings("unused") @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display help information.") private boolean helpRequested; void execute(String... args) { toCommandLine().execute(args); } void parseArgs(String... args) { toCommandLine().parseArgs(args); } private CommandLine toCommandLine() { return BaseCommand.initialize(new CommandLine(this)); } static CommandLine initialize(CommandLine commandLine) { CommandLine.IParameterExceptionHandler defaultParameterExceptionHandler = commandLine.getParameterExceptionHandler(); return commandLine // .setParameterExceptionHandler((ex, args) -> { defaultParameterExceptionHandler.handleParseException(ex, args); return CommandResult.FAILURE; }) // .setExecutionExceptionHandler((ex, cmd, __) -> { commandLine.getErr().println(cmd.getColorScheme().richStackTraceString(ex)); commandLine.getErr().println(); commandLine.getErr().flush(); cmd.usage(commandLine.getOut()); return CommandResult.FAILURE; }) // .setCaseInsensitiveEnumValuesAllowed(true) // .setAtFileCommentChar(null); } @Override public final T call() { PrintWriter out = getOut(); if (!outputOptions.isDisableBanner()) { displayBanner(out); } try { return execute(out); } catch (PreconditionViolationException e) { throw new ParameterException(commandSpec.commandLine(), e.getMessage(), e.getCause()); } } private PrintWriter getOut() { return commandSpec.commandLine().getOut(); } private void displayBanner(PrintWriter out) { out.println(); CommandLine.Help.ColorScheme colorScheme = getColorScheme(); if (colorScheme.ansi().enabled()) { out.print("💚 "); } out.println(colorScheme.string( "@|italic Thanks for using JUnit!|@ Support its development at @|underline https://junit.org/sponsoring|@")); out.println(); out.flush(); } protected final CommandLine.Help.ColorScheme getColorScheme() { return commandSpec.commandLine().getColorScheme(); } protected abstract T execute(PrintWriter out); } ClasspathEntriesConverter.java000066400000000000000000000014361455764576500371330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import picocli.CommandLine; class ClasspathEntriesConverter implements CommandLine.ITypeConverter> { @Override public List convert(String value) { return Stream.of(value.split(File.pathSeparator)).map(Paths::get).collect(Collectors.toList()); } } CommandFacade.java000066400000000000000000000021461455764576500344300ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.PrintWriter; import org.apiguardian.api.API; import org.junit.platform.console.tasks.ConsoleTestExecutor; /** * Internal facade to run a CLI command that exists to hide implementation * details such as the used library. * * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public class CommandFacade { private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; public CommandFacade(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { this.consoleTestExecutorFactory = consoleTestExecutorFactory; } public CommandResult run(PrintWriter out, PrintWriter err, String[] args) { return new MainCommand(consoleTestExecutorFactory).run(out, err, args); } } CommandResult.java000066400000000000000000000024621455764576500345440ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Optional; import org.apiguardian.api.API; /** * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public class CommandResult { /** * Exit code indicating successful execution */ public static final int SUCCESS = 0; /** * Exit code indicating any failure(s) */ protected static final int FAILURE = -1; public static CommandResult success() { return create(SUCCESS, null); } public static CommandResult failure() { return create(FAILURE, null); } public static CommandResult create(int exitCode, T value) { return new CommandResult<>(exitCode, value); } private final int exitCode; private final T value; private CommandResult(int exitCode, T value) { this.exitCode = exitCode; this.value = value; } public int getExitCode() { return exitCode; } public Optional getValue() { return Optional.ofNullable(value); } } ConsoleUtils.java000066400000000000000000000017431455764576500344130ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.nio.charset.Charset; import org.apiguardian.api.API; /** * Collection of utilities for working with {@code java.io.Console} * and friends. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.9 */ @API(status = INTERNAL, since = "1.9") public class ConsoleUtils { /** * {@return the charset of the console} */ public static Charset charset() { return Charset.defaultCharset(); } } junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/Details.java000066400000000000000000000022711455764576500334310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; /** * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public enum Details { /** * No test plan execution details are printed. */ NONE, /** * Print summary table of counts only. */ SUMMARY, /** * Test plan execution details are rendered in a flat, line-by-line mode. */ FLAT, /** * Test plan execution details are rendered as a simple tree. */ TREE, /** * Combines {@link #TREE} and {@link #FLAT} modes. */ VERBOSE, /** * Test plan execution events are rendered as they occur in a concise format. * * @since 1.10 */ TESTFEED; /** * Return lower case {@link #name()} for easier usage in help text for * available options. */ @Override public String toString() { return name().toLowerCase(); } } DiscoverTestsCommand.java000066400000000000000000000026161455764576500360700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.io.PrintWriter; import org.junit.platform.console.tasks.ConsoleTestExecutor; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; @Command(// name = "discover", // description = "Discover tests" // ) class DiscoverTestsCommand extends BaseCommand { private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; @Mixin TestDiscoveryOptionsMixin discoveryOptions; @Mixin TestConsoleOutputOptionsMixin testOutputOptions; DiscoverTestsCommand(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { this.consoleTestExecutorFactory = consoleTestExecutorFactory; } @Override protected Void execute(PrintWriter out) { TestDiscoveryOptions discoveryOptions = this.discoveryOptions.toTestDiscoveryOptions(); TestConsoleOutputOptions testOutputOptions = this.testOutputOptions.toTestConsoleOutputOptions(); testOutputOptions.setAnsiColorOutputDisabled(outputOptions.isDisableAnsiColors()); consoleTestExecutorFactory.create(discoveryOptions, testOutputOptions).discover(out); return null; } } ExecuteTestsCommand.java000066400000000000000000000067731455764576500357240ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.junit.platform.console.options.CommandResult.SUCCESS; import java.io.PrintWriter; import java.nio.file.Path; import java.util.Optional; import org.junit.platform.console.tasks.ConsoleTestExecutor; import org.junit.platform.launcher.listeners.TestExecutionSummary; import picocli.CommandLine; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; @Command(// name = "execute", // description = "Execute tests" // ) class ExecuteTestsCommand extends BaseCommand implements CommandLine.IExitCodeGenerator { /** * Exit code indicating test failure(s) */ private static final int TEST_FAILED = 1; /** * Exit code indicating no tests found */ private static final int NO_TESTS_FOUND = 2; private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; @Mixin TestDiscoveryOptionsMixin discoveryOptions; @Mixin TestConsoleOutputOptionsMixin testOutputOptions; @ArgGroup(validate = false, order = 6, heading = "%n@|bold REPORTING|@%n%n") ReportingOptions reportingOptions; ExecuteTestsCommand(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { this.consoleTestExecutorFactory = consoleTestExecutorFactory; } @Override protected TestExecutionSummary execute(PrintWriter out) { return consoleTestExecutorFactory.create(toTestDiscoveryOptions(), toTestConsoleOutputOptions()) // .execute(out, getReportsDir()); } Optional getReportsDir() { return getReportingOptions().flatMap(ReportingOptions::getReportsDir); } private Optional getReportingOptions() { return Optional.ofNullable(reportingOptions); } TestDiscoveryOptions toTestDiscoveryOptions() { return this.discoveryOptions == null // ? new TestDiscoveryOptions() // : this.discoveryOptions.toTestDiscoveryOptions(); } TestConsoleOutputOptions toTestConsoleOutputOptions() { TestConsoleOutputOptions testOutputOptions = this.testOutputOptions.toTestConsoleOutputOptions(); testOutputOptions.setAnsiColorOutputDisabled(outputOptions.isDisableAnsiColors()); return testOutputOptions; } @Override public int getExitCode() { TestExecutionSummary executionResult = commandSpec.commandLine().getExecutionResult(); boolean failIfNoTests = getReportingOptions().map(it -> it.failIfNoTests).orElse(false); if (failIfNoTests && executionResult.getTestsFoundCount() == 0) { return NO_TESTS_FOUND; } return executionResult.getTotalFailureCount() == 0 ? SUCCESS : TEST_FAILED; } static class ReportingOptions { @CommandLine.Option(names = "--fail-if-no-tests", description = "Fail and return exit status code 2 if no tests are found.") private boolean failIfNoTests; // no single-dash equivalent: was introduced in 5.3-M1 @CommandLine.Option(names = "--reports-dir", paramLabel = "DIR", description = "Enable report output into a specified local directory (will be created if it does not exist).") private Path reportsDir; @CommandLine.Option(names = "-reports-dir", hidden = true) private Path reportsDir2; Optional getReportsDir() { return reportsDir == null ? Optional.ofNullable(reportsDir2) : Optional.of(reportsDir); } } } ListTestEnginesCommand.java000066400000000000000000000031271455764576500363510ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.io.PrintWriter; import java.util.Comparator; import java.util.StringJoiner; import java.util.stream.StreamSupport; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry; import picocli.CommandLine.Command; @Command(// name = "engines", // description = "List available test engines" // ) class ListTestEnginesCommand extends BaseCommand { @Override protected Void execute(PrintWriter out) { displayEngines(out); return null; } void displayEngines(PrintWriter out) { ServiceLoaderTestEngineRegistry registry = new ServiceLoaderTestEngineRegistry(); Iterable engines = registry.loadTestEngines(); StreamSupport.stream(engines.spliterator(), false) // .sorted(Comparator.comparing(TestEngine::getId)) // .forEach(engine -> displayEngine(out, engine)); out.flush(); } private void displayEngine(PrintWriter out, TestEngine engine) { StringJoiner details = new StringJoiner(":", " (", ")"); engine.getGroupId().ifPresent(details::add); engine.getArtifactId().ifPresent(details::add); engine.getVersion().ifPresent(details::add); out.println(getColorScheme().string(String.format("@|bold %s|@%s", engine.getId(), details))); } } MainCommand.java000066400000000000000000000125131455764576500341500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.Callable; import org.junit.platform.console.tasks.ConsoleTestExecutor; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Help.ColorScheme; import picocli.CommandLine.IExitCodeGenerator; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; import picocli.CommandLine.Spec; import picocli.CommandLine.Unmatched; @Command(// name = "junit", // abbreviateSynopsis = true, // sortOptions = false, // usageHelpWidth = 95, // showAtFileInUsageHelp = true, // usageHelpAutoWidth = true, // description = "Launches the JUnit Platform for test discovery and execution.", // footerHeading = "%n", // footer = "For more information, please refer to the JUnit User Guide at%n" // + "@|underline https://junit.org/junit5/docs/current/user-guide/|@", // scope = CommandLine.ScopeType.INHERIT, // exitCodeOnInvalidInput = CommandResult.FAILURE, // exitCodeOnExecutionException = CommandResult.FAILURE // ) class MainCommand implements Callable, IExitCodeGenerator { private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; @Option(names = { "-h", "--help" }, help = true, hidden = true) private boolean helpRequested; @Option(names = { "--h", "-help" }, help = true, hidden = true) private boolean helpRequested2; @Unmatched private List allParameters = new ArrayList<>(); @Spec CommandSpec commandSpec; CommandResult commandResult; MainCommand(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { this.consoleTestExecutorFactory = consoleTestExecutorFactory; } @Override public Object call() { if (helpRequested || helpRequested2) { commandSpec.commandLine().usage(commandSpec.commandLine().getOut()); commandResult = CommandResult.success(); return null; } if (allParameters.contains("--list-engines")) { return runCommand("engines", Optional.of("--list-engines")); } return runCommand("execute", Optional.empty()); } @Override public int getExitCode() { return commandResult.getExitCode(); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private Object runCommand(String subcommand, Optional triggeringOption) { CommandLine commandLine = commandSpec.commandLine(); commandLine.setUnmatchedArgumentsAllowed(false); Object command = commandLine.getSubcommands().get(subcommand).getCommandSpec().userObject(); List args = new ArrayList<>(commandLine.getParseResult().expandedArgs()); triggeringOption.ifPresent(args::remove); CommandResult result = runCommand(commandLine.getOut(), // commandLine.getErr(), // args.toArray(new String[0]), // command); this.commandResult = result; printDeprecationWarning(subcommand, triggeringOption, commandLine); return result.getValue().orElse(null); } private static void printDeprecationWarning(String subcommand, Optional triggeringOption, CommandLine commandLine) { PrintWriter err = commandLine.getErr(); String reason = triggeringOption.map(it -> " due to use of '" + it + "'").orElse(""); commandLine.getOut().flush(); err.println(); ColorScheme colorScheme = commandLine.getColorScheme(); err.println(colorScheme.string( String.format("@|yellow,bold WARNING:|@ Delegated to the '%s' command%s.", subcommand, reason))); err.println( colorScheme.string(" This behaviour has been deprecated and will be removed in a future release.")); err.println(colorScheme.string(" Please use the '" + subcommand + "' command directly.")); err.flush(); } CommandResult run(PrintWriter out, PrintWriter err, String[] args) { CommandLine commandLine = new CommandLine(this) // .addSubcommand(new DiscoverTestsCommand(consoleTestExecutorFactory)) // .addSubcommand(new ExecuteTestsCommand(consoleTestExecutorFactory)) // .addSubcommand(new ListTestEnginesCommand()); return runCommand(out, err, args, commandLine); } private static CommandResult runCommand(PrintWriter out, PrintWriter err, String[] args, Object command) { return runCommand(out, err, args, new CommandLine(command)); } private static CommandResult runCommand(PrintWriter out, PrintWriter err, String[] args, CommandLine commandLine) { int exitCode = BaseCommand.initialize(commandLine) // .setOut(out) // .setErr(err) // .execute(args); return CommandResult.create(exitCode, getLikelyExecutedCommand(commandLine).getExecutionResult()); } /** * Get the most likely executed subcommand, if any, or the main command otherwise. * @see Executing Commands with Subcommands */ private static CommandLine getLikelyExecutedCommand(final CommandLine commandLine) { return Optional.ofNullable(commandLine.getParseResult().subcommand()) // .map(parseResult -> parseResult.commandSpec().commandLine()) // .orElse(commandLine); } } OutputOptionsMixin.java000066400000000000000000000031121455764576500356410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static picocli.CommandLine.Help.defaultColorScheme; import static picocli.CommandLine.Spec.Target.MIXEE; import picocli.CommandLine.Help.Ansi; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; import picocli.CommandLine.Spec; class OutputOptionsMixin { @Spec(MIXEE) CommandSpec commandSpec; @Option(names = "--disable-banner", description = "Disable print out of the welcome message.") private boolean disableBanner; @Option(names = "-disable-banner", hidden = true) private boolean disableBanner2; private boolean disableAnsiColors; public boolean isDisableBanner() { return disableBanner || disableBanner2; } public boolean isDisableAnsiColors() { return disableAnsiColors; } @Option(names = "--disable-ansi-colors", description = "Disable ANSI colors in output (not supported by all terminals).") public void setDisableAnsiColors(boolean disableAnsiColors) { if (disableAnsiColors) { commandSpec.commandLine().setColorScheme(defaultColorScheme(Ansi.OFF)); } this.disableAnsiColors = disableAnsiColors; } @Option(names = "-disable-ansi-colors", hidden = true) public void setDisableAnsiColors2(boolean disableAnsiColors) { setDisableAnsiColors(disableAnsiColors); } } SelectorConverter.java000066400000000000000000000116371455764576500354430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathResource; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectFile; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModule; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.IntStream; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; import picocli.CommandLine.ITypeConverter; class SelectorConverter { static class Module implements ITypeConverter { @Override public ModuleSelector convert(String value) { return selectModule(value); } } static class Uri implements ITypeConverter { @Override public UriSelector convert(String value) { return selectUri(value); } } static class File implements ITypeConverter { @Override public FileSelector convert(String value) { return selectFile(value); } } static class Directory implements ITypeConverter { @Override public DirectorySelector convert(String value) { return selectDirectory(value); } } static class Package implements ITypeConverter { @Override public PackageSelector convert(String value) { return selectPackage(value); } } static class Class implements ITypeConverter { @Override public ClassSelector convert(String value) { return selectClass(value); } } static class Method implements ITypeConverter { @Override public MethodSelector convert(String value) { return selectMethod(value); } } static class ClasspathResource implements ITypeConverter { @Override public ClasspathResourceSelector convert(String value) { return selectClasspathResource(value); } } static class Iteration implements ITypeConverter { public static final Pattern PATTERN = Pattern.compile( "(?[a-z]+):(?.*)\\[(?(\\d+)(\\.\\.\\d+)?(\\s*,\\s*(\\d+)(\\.\\.\\d+)?)*)]"); @Override public IterationSelector convert(String value) { Matcher matcher = PATTERN.matcher(value); Preconditions.condition(matcher.matches(), "Invalid format: must be TYPE:VALUE[INDEX(,INDEX)*]"); DiscoverySelector parentSelector = createParentSelector(matcher.group("type"), matcher.group("value")); int[] iterationIndices = Arrays.stream(matcher.group("indices").split(",")) // .flatMapToInt(this::parseIndexDefinition) // .toArray(); return selectIteration(parentSelector, iterationIndices); } private IntStream parseIndexDefinition(String value) { String[] parts = value.split("\\.\\.", 2); int firstIndex = Integer.parseInt(parts[0]); if (parts.length == 2) { int lastIndex = Integer.parseInt(parts[1]); return IntStream.rangeClosed(firstIndex, lastIndex); } return IntStream.of(firstIndex); } private DiscoverySelector createParentSelector(String type, String value) { switch (type) { case "module": return selectModule(value); case "uri": return selectUri(value); case "file": return selectFile(value); case "directory": return selectDirectory(value); case "package": return selectPackage(value); case "class": return selectClass(value); case "method": return selectMethod(value); case "resource": return selectClasspathResource(value); default: throw new IllegalArgumentException("Unknown type: " + type); } } } } TestConsoleOutputOptions.java000066400000000000000000000035251455764576500370270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.nio.file.Path; import java.util.Locale; import org.apiguardian.api.API; /** * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public class TestConsoleOutputOptions { static final String DEFAULT_DETAILS_NAME = "tree"; static final Details DEFAULT_DETAILS = Details.valueOf(DEFAULT_DETAILS_NAME.toUpperCase(Locale.ROOT)); static final Theme DEFAULT_THEME = Theme.valueOf(ConsoleUtils.charset()); private boolean ansiColorOutputDisabled; private Path colorPalettePath; private boolean isSingleColorPalette; private Details details = DEFAULT_DETAILS; private Theme theme = DEFAULT_THEME; public boolean isAnsiColorOutputDisabled() { return this.ansiColorOutputDisabled; } public void setAnsiColorOutputDisabled(boolean ansiColorOutputDisabled) { this.ansiColorOutputDisabled = ansiColorOutputDisabled; } public Path getColorPalettePath() { return colorPalettePath; } public void setColorPalettePath(Path colorPalettePath) { this.colorPalettePath = colorPalettePath; } public boolean isSingleColorPalette() { return isSingleColorPalette; } public void setSingleColorPalette(boolean singleColorPalette) { this.isSingleColorPalette = singleColorPalette; } public Details getDetails() { return this.details; } public void setDetails(Details details) { this.details = details; } public Theme getTheme() { return this.theme; } public void setTheme(Theme theme) { this.theme = theme; } } TestConsoleOutputOptionsMixin.java000066400000000000000000000060731455764576500400350ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.junit.platform.console.options.TestConsoleOutputOptions.DEFAULT_DETAILS; import static org.junit.platform.console.options.TestConsoleOutputOptions.DEFAULT_DETAILS_NAME; import static org.junit.platform.console.options.TestConsoleOutputOptions.DEFAULT_THEME; import java.nio.file.Path; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Option; class TestConsoleOutputOptionsMixin { @ArgGroup(validate = false, order = 5, heading = "%n@|bold CONSOLE OUTPUT|@%n%n") ConsoleOutputOptions consoleOutputOptions = new ConsoleOutputOptions(); static class ConsoleOutputOptions { @Option(names = "--color-palette", paramLabel = "FILE", description = "Specify a path to a properties file to customize ANSI style of output (not supported by all terminals).") private Path colorPalette; @Option(names = "-color-palette", hidden = true) private Path colorPalette2; @Option(names = "--single-color", description = "Style test output using only text attributes, no color (not supported by all terminals).") private boolean singleColorPalette; @Option(names = "-single-color", hidden = true) private boolean singleColorPalette2; @Option(names = "--details", paramLabel = "MODE", defaultValue = DEFAULT_DETAILS_NAME, description = "Select an output details mode for when tests are executed. " // + "Use one of: ${COMPLETION-CANDIDATES}. If 'none' is selected, " // + "then only the summary and test failures are shown. Default: ${DEFAULT-VALUE}.") private Details details = DEFAULT_DETAILS; @Option(names = "-details", hidden = true, defaultValue = DEFAULT_DETAILS_NAME) private Details details2 = DEFAULT_DETAILS; @Option(names = "--details-theme", paramLabel = "THEME", description = "Select an output details tree theme for when tests are executed. " + "Use one of: ${COMPLETION-CANDIDATES}. Default is detected based on default character encoding.") private Theme theme = DEFAULT_THEME; @Option(names = "-details-theme", hidden = true) private Theme theme2 = DEFAULT_THEME; private void applyTo(TestConsoleOutputOptions result) { result.setColorPalettePath(choose(colorPalette, colorPalette2, null)); result.setSingleColorPalette(singleColorPalette || singleColorPalette2); result.setDetails(choose(details, details2, DEFAULT_DETAILS)); result.setTheme(choose(theme, theme2, DEFAULT_THEME)); } } TestConsoleOutputOptions toTestConsoleOutputOptions() { TestConsoleOutputOptions result = new TestConsoleOutputOptions(); if (this.consoleOutputOptions != null) { this.consoleOutputOptions.applyTo(result); } return result; } private static T choose(T left, T right, T defaultValue) { return left == right ? left : (left == defaultValue ? right : left); } } TestDiscoveryOptions.java000066400000000000000000000200641455764576500361500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apiguardian.api.API; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; /** * @since 1.10 */ @API(status = INTERNAL, since = "1.10") public class TestDiscoveryOptions { private boolean scanClasspath; private List additionalClasspathEntries = emptyList(); private List selectedClasspathEntries = emptyList(); private boolean scanModulepath; private List selectedModules = emptyList(); private List selectedUris = emptyList(); private List selectedFiles = emptyList(); private List selectedDirectories = emptyList(); private List selectedPackages = emptyList(); private List selectedClasses = emptyList(); private List selectedMethods = emptyList(); private List selectedClasspathResources = emptyList(); private List selectedIterations = emptyList(); private List includedClassNamePatterns = singletonList(STANDARD_INCLUDE_PATTERN); private List excludedClassNamePatterns = emptyList(); private List includedPackages = emptyList(); private List excludedPackages = emptyList(); private List includedEngines = emptyList(); private List excludedEngines = emptyList(); private List includedTagExpressions = emptyList(); private List excludedTagExpressions = emptyList(); private Map configurationParameters = emptyMap(); public boolean isScanModulepath() { return this.scanModulepath; } public void setScanModulepath(boolean scanModulepath) { this.scanModulepath = scanModulepath; } public boolean isScanClasspath() { return this.scanClasspath; } public void setScanClasspath(boolean scanClasspath) { this.scanClasspath = scanClasspath; } public List getExistingAdditionalClasspathEntries() { return this.additionalClasspathEntries.stream().filter(Files::exists).collect(toList()); } public List getAdditionalClasspathEntries() { return this.additionalClasspathEntries; } public void setAdditionalClasspathEntries(List additionalClasspathEntries) { this.additionalClasspathEntries = additionalClasspathEntries; } public List getSelectedClasspathEntries() { return this.selectedClasspathEntries; } public void setSelectedClasspathEntries(List selectedClasspathEntries) { this.selectedClasspathEntries = selectedClasspathEntries; } public List getSelectedUris() { return selectedUris; } public void setSelectedUris(List selectedUris) { this.selectedUris = selectedUris; } public List getSelectedFiles() { return selectedFiles; } public void setSelectedFiles(List selectedFiles) { this.selectedFiles = selectedFiles; } public List getSelectedDirectories() { return selectedDirectories; } public void setSelectedDirectories(List selectedDirectories) { this.selectedDirectories = selectedDirectories; } public List getSelectedModules() { return selectedModules; } public void setSelectedModules(List selectedModules) { this.selectedModules = selectedModules; } public List getSelectedPackages() { return selectedPackages; } public void setSelectedPackages(List selectedPackages) { this.selectedPackages = selectedPackages; } public List getSelectedClasses() { return selectedClasses; } public void setSelectedClasses(List selectedClasses) { this.selectedClasses = selectedClasses; } public List getSelectedMethods() { return selectedMethods; } public void setSelectedMethods(List selectedMethods) { this.selectedMethods = selectedMethods; } public List getSelectedClasspathResources() { return selectedClasspathResources; } public void setSelectedClasspathResources(List selectedClasspathResources) { this.selectedClasspathResources = selectedClasspathResources; } public List getSelectedIterations() { return selectedIterations; } public void setSelectedIterations(List selectedIterations) { this.selectedIterations = selectedIterations; } public List getExplicitSelectors() { List selectors = new ArrayList<>(); selectors.addAll(getSelectedUris()); selectors.addAll(getSelectedFiles()); selectors.addAll(getSelectedDirectories()); selectors.addAll(getSelectedModules()); selectors.addAll(getSelectedPackages()); selectors.addAll(getSelectedClasses()); selectors.addAll(getSelectedMethods()); selectors.addAll(getSelectedClasspathResources()); selectors.addAll(getSelectedIterations()); return selectors; } public List getIncludedClassNamePatterns() { return this.includedClassNamePatterns; } public void setIncludedClassNamePatterns(List includedClassNamePatterns) { this.includedClassNamePatterns = includedClassNamePatterns; } public List getExcludedClassNamePatterns() { return this.excludedClassNamePatterns; } public void setExcludedClassNamePatterns(List excludedClassNamePatterns) { this.excludedClassNamePatterns = excludedClassNamePatterns; } public List getIncludedPackages() { return this.includedPackages; } public void setIncludedPackages(List includedPackages) { this.includedPackages = includedPackages; } public List getExcludedPackages() { return this.excludedPackages; } public void setExcludedPackages(List excludedPackages) { this.excludedPackages = excludedPackages; } public List getIncludedEngines() { return this.includedEngines; } public void setIncludedEngines(List includedEngines) { this.includedEngines = includedEngines; } public List getExcludedEngines() { return this.excludedEngines; } public void setExcludedEngines(List excludedEngines) { this.excludedEngines = excludedEngines; } public List getIncludedTagExpressions() { return this.includedTagExpressions; } public void setIncludedTagExpressions(List includedTags) { this.includedTagExpressions = includedTags; } public List getExcludedTagExpressions() { return this.excludedTagExpressions; } public void setExcludedTagExpressions(List excludedTags) { this.excludedTagExpressions = excludedTags; } public Map getConfigurationParameters() { return this.configurationParameters; } public void setConfigurationParameters(Map configurationParameters) { this.configurationParameters = configurationParameters; } } TestDiscoveryOptionsMixin.java000066400000000000000000000371671455764576500371710ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; import picocli.CommandLine; import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Option; class TestDiscoveryOptionsMixin { private static final String CP_OPTION = "cp"; @ArgGroup(validate = false, order = 2, heading = "%n@|bold SELECTORS|@%n%n") SelectorOptions selectorOptions; @ArgGroup(validate = false, order = 3, heading = "%n@|bold FILTERS|@%n%n") FilterOptions filterOptions; @ArgGroup(validate = false, order = 4, heading = "%n@|bold RUNTIME CONFIGURATION|@%n%n") RuntimeConfigurationOptions runtimeConfigurationOptions; static class SelectorOptions { @Option(names = { "--scan-classpath", "--scan-class-path" }, converter = ClasspathEntriesConverter.class, paramLabel = "PATH", arity = "0..1", description = "Scan all directories on the classpath or explicit classpath roots. " // + "Without arguments, only directories on the system classpath as well as additional classpath " // + "entries supplied via -" + CP_OPTION + " (directories and JAR files) are scanned. " // + "Explicit classpath roots that are not on the classpath will be silently ignored. " // + "This option can be repeated.") private List selectedClasspathEntries; @Option(names = { "-scan-class-path", "-scan-classpath" }, converter = ClasspathEntriesConverter.class, arity = "0..1", hidden = true) private List selectedClasspathEntries2; @Option(names = "--scan-modules", description = "Scan all resolved modules for test discovery.") private boolean scanModulepath; @Option(names = "-scan-modules", hidden = true) private boolean scanModulepath2; @Option(names = { "-u", "--select-uri" }, paramLabel = "URI", arity = "1", converter = SelectorConverter.Uri.class, description = "Select a URI for test discovery. This option can be repeated.") private List selectedUris = new ArrayList<>(); @Option(names = { "--u", "-select-uri" }, arity = "1", hidden = true, converter = SelectorConverter.Uri.class) private List selectedUris2 = new ArrayList<>(); @Option(names = { "-f", "--select-file" }, paramLabel = "FILE", arity = "1", converter = SelectorConverter.File.class, description = "Select a file for test discovery. This option can be repeated.") private List selectedFiles = new ArrayList<>(); @Option(names = { "--f", "-select-file" }, arity = "1", hidden = true, converter = SelectorConverter.File.class) private List selectedFiles2 = new ArrayList<>(); @Option(names = { "-d", "--select-directory" }, paramLabel = "DIR", arity = "1", converter = SelectorConverter.Directory.class, description = "Select a directory for test discovery. This option can be repeated.") private List selectedDirectories = new ArrayList<>(); @Option(names = { "--d", "-select-directory" }, arity = "1", hidden = true, converter = SelectorConverter.Directory.class) private List selectedDirectories2 = new ArrayList<>(); @Option(names = { "-o", "--select-module" }, paramLabel = "NAME", arity = "1", converter = SelectorConverter.Module.class, description = "Select single module for test discovery. This option can be repeated.") private List selectedModules = new ArrayList<>(); @Option(names = { "--o", "-select-module" }, arity = "1", converter = SelectorConverter.Module.class, hidden = true) private List selectedModules2 = new ArrayList<>(); @Option(names = { "-p", "--select-package" }, paramLabel = "PKG", arity = "1", converter = SelectorConverter.Package.class, description = "Select a package for test discovery. This option can be repeated.") private List selectedPackages = new ArrayList<>(); @Option(names = { "--p", "-select-package" }, arity = "1", hidden = true, converter = SelectorConverter.Package.class) private List selectedPackages2 = new ArrayList<>(); @Option(names = { "-c", "--select-class" }, paramLabel = "CLASS", arity = "1", converter = SelectorConverter.Class.class, description = "Select a class for test discovery. This option can be repeated.") private List selectedClasses = new ArrayList<>(); @Option(names = { "--c", "-select-class" }, arity = "1", hidden = true, converter = SelectorConverter.Class.class) private List selectedClasses2 = new ArrayList<>(); @Option(names = { "-m", "--select-method" }, paramLabel = "NAME", arity = "1", converter = SelectorConverter.Method.class, description = "Select a method for test discovery. This option can be repeated.") private List selectedMethods = new ArrayList<>(); @Option(names = { "--m", "-select-method" }, arity = "1", hidden = true, converter = SelectorConverter.Method.class) private List selectedMethods2 = new ArrayList<>(); @Option(names = { "-r", "--select-resource" }, paramLabel = "RESOURCE", arity = "1", converter = SelectorConverter.ClasspathResource.class, description = "Select a classpath resource for test discovery. This option can be repeated.") private List selectedClasspathResources = new ArrayList<>(); @Option(names = { "--r", "-select-resource" }, arity = "1", hidden = true, converter = SelectorConverter.ClasspathResource.class) private List selectedClasspathResources2 = new ArrayList<>(); @Option(names = { "-i", "--select-iteration" }, paramLabel = "TYPE:VALUE[INDEX(..INDEX)?(,INDEX(..INDEX)?)*]", arity = "1", converter = SelectorConverter.Iteration.class, description = "Select iterations for test discovery (e.g. method:com.acme.Foo#m()[1..2]). This option can be repeated.") private List selectedIterations = new ArrayList<>(); @Option(names = { "--i", "-select-iteration" }, arity = "1", hidden = true, converter = SelectorConverter.Iteration.class) private List selectedIterations2 = new ArrayList<>(); SelectorOptions() { } private void applyTo(TestDiscoveryOptions result) { result.setScanClasspath(this.selectedClasspathEntries != null || this.selectedClasspathEntries2 != null); // flag was specified result.setScanModulepath(this.scanModulepath || this.scanModulepath2); result.setSelectedModules(merge(this.selectedModules, this.selectedModules2)); result.setSelectedClasspathEntries(merge(this.selectedClasspathEntries, this.selectedClasspathEntries2)); result.setSelectedUris(merge(this.selectedUris, this.selectedUris2)); result.setSelectedFiles(merge(this.selectedFiles, this.selectedFiles2)); result.setSelectedDirectories(merge(this.selectedDirectories, this.selectedDirectories2)); result.setSelectedPackages(merge(this.selectedPackages, this.selectedPackages2)); result.setSelectedClasses(merge(this.selectedClasses, this.selectedClasses2)); result.setSelectedMethods(merge(this.selectedMethods, this.selectedMethods2)); result.setSelectedClasspathResources( merge(this.selectedClasspathResources, this.selectedClasspathResources2)); result.setSelectedIterations(merge(this.selectedIterations, this.selectedIterations2)); } } static class FilterOptions { @Option(names = { "-n", "--include-classname" }, paramLabel = "PATTERN", defaultValue = ClassNameFilter.STANDARD_INCLUDE_PATTERN, arity = "1", description = "Provide a regular expression to include only classes whose fully qualified names match. " // + "To avoid loading classes unnecessarily, the default pattern only includes class " // + "names that begin with \"Test\" or end with \"Test\" or \"Tests\". " // + "When this option is repeated, all patterns will be combined using OR semantics. " // + "Default: ${DEFAULT-VALUE}") private List includeClassNamePatterns = new ArrayList<>(); @Option(names = { "--n", "-include-classname" }, arity = "1", hidden = true) private List includeClassNamePatterns2 = new ArrayList<>(); @Option(names = { "-N", "--exclude-classname" }, paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to exclude those classes whose fully qualified names match. " // + "When this option is repeated, all patterns will be combined using OR semantics.") private List excludeClassNamePatterns = new ArrayList<>(); @Option(names = { "--N", "-exclude-classname" }, arity = "1", hidden = true) private List excludeClassNamePatterns2 = new ArrayList<>(); @Option(names = { "--include-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be included in the test run. This option can be repeated.") private List includePackages = new ArrayList<>(); @Option(names = { "-include-package" }, arity = "1", hidden = true) private List includePackages2 = new ArrayList<>(); @Option(names = { "--exclude-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be excluded from the test run. This option can be repeated.") private List excludePackages = new ArrayList<>(); @Option(names = { "-exclude-package" }, arity = "1", hidden = true) private List excludePackages2 = new ArrayList<>(); @Option(names = { "-t", "--include-tag" }, paramLabel = "TAG", arity = "1", description = "Provide a tag or tag expression to include only tests whose tags match. " + // "When this option is repeated, all patterns will be combined using OR semantics.") private List includedTags = new ArrayList<>(); @Option(names = { "--t", "-include-tag" }, arity = "1", hidden = true) private List includedTags2 = new ArrayList<>(); @Option(names = { "-T", "--exclude-tag" }, paramLabel = "TAG", arity = "1", description = "Provide a tag or tag expression to exclude those tests whose tags match. " + // "When this option is repeated, all patterns will be combined using OR semantics.") private List excludedTags = new ArrayList<>(); @Option(names = { "--T", "-exclude-tag" }, arity = "1", hidden = true) private List excludedTags2 = new ArrayList<>(); @Option(names = { "-e", "--include-engine" }, paramLabel = "ID", arity = "1", description = "Provide the ID of an engine to be included in the test run. This option can be repeated.") private List includedEngines = new ArrayList<>(); @Option(names = { "--e", "-include-engine" }, arity = "1", hidden = true) private List includedEngines2 = new ArrayList<>(); @Option(names = { "-E", "--exclude-engine" }, paramLabel = "ID", arity = "1", description = "Provide the ID of an engine to be excluded from the test run. This option can be repeated.") private List excludedEngines = new ArrayList<>(); @Option(names = { "--E", "-exclude-engine" }, arity = "1", hidden = true) private List excludedEngines2 = new ArrayList<>(); private void applyTo(TestDiscoveryOptions result) { result.setIncludedClassNamePatterns(merge(this.includeClassNamePatterns, this.includeClassNamePatterns2)); result.setExcludedClassNamePatterns(merge(this.excludeClassNamePatterns, this.excludeClassNamePatterns2)); result.setIncludedPackages(merge(this.includePackages, this.includePackages2)); result.setExcludedPackages(merge(this.excludePackages, this.excludePackages2)); result.setIncludedTagExpressions(merge(this.includedTags, this.includedTags2)); result.setExcludedTagExpressions(merge(this.excludedTags, this.excludedTags2)); result.setIncludedEngines(merge(this.includedEngines, this.includedEngines2)); result.setExcludedEngines(merge(this.excludedEngines, this.excludedEngines2)); } } static class RuntimeConfigurationOptions { @Option(names = { "-" + CP_OPTION, "--classpath", "--class-path" }, converter = ClasspathEntriesConverter.class, paramLabel = "PATH", arity = "1", description = "Provide additional classpath entries " + "-- for example, for adding engines and their dependencies. This option can be repeated.") private List additionalClasspathEntries = new ArrayList<>(); @Option(names = { "--cp", "-classpath", "-class-path" }, converter = ClasspathEntriesConverter.class, hidden = true) private List additionalClasspathEntries2 = new ArrayList<>(); // Implementation note: the @Option annotation is on a setter method to allow validation. private Map configurationParameters = new LinkedHashMap<>(); @CommandLine.Spec private CommandLine.Model.CommandSpec spec; @Option(names = { "-config" }, arity = "1", hidden = true) public void setConfigurationParameters2(Map keyValuePairs) { setConfigurationParameters(keyValuePairs); } /** * Adds the specified key-value pair (or pairs) to the configuration parameters. * A {@code ParameterException} is thrown if the same key is specified multiple times * on the command line. * * @param map the key-value pairs to add * @throws CommandLine.ParameterException if the map already contains this key * @see #1308 */ @Option(names = "--config", paramLabel = "KEY=VALUE", arity = "1", description = "Set a configuration parameter for test discovery and execution. This option can be repeated.") public void setConfigurationParameters(Map map) { for (String key : map.keySet()) { String newValue = map.get(key); validateUnique(key, newValue); configurationParameters.put(key, newValue); } } private void validateUnique(String key, String newValue) { String existing = configurationParameters.get(key); if (existing != null && !existing.equals(newValue)) { throw new CommandLine.ParameterException(spec.commandLine(), String.format("Duplicate key '%s' for values '%s' and '%s'.", key, existing, newValue)); } } private void applyTo(TestDiscoveryOptions result) { result.setAdditionalClasspathEntries(merge(additionalClasspathEntries, additionalClasspathEntries2)); result.setConfigurationParameters(configurationParameters); } } TestDiscoveryOptions toTestDiscoveryOptions() { TestDiscoveryOptions result = new TestDiscoveryOptions(); if (this.selectorOptions != null) { this.selectorOptions.applyTo(result); } if (this.filterOptions != null) { this.filterOptions.applyTo(result); } if (this.runtimeConfigurationOptions != null) { this.runtimeConfigurationOptions.applyTo(result); } return result; } private static List merge(List list1, List list2) { List result = new ArrayList<>(list1 == null ? Collections.emptyList() : list1); result.addAll(list2 == null ? Collections.emptyList() : list2); return result; } } junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/Theme.java000066400000000000000000000057361455764576500331170ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.apiguardian.api.API; import org.junit.platform.engine.TestExecutionResult; /** * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public enum Theme { /** * ASCII 7-bit characters form the tree branch. * *

Example test plan execution tree: *

	 * +-- engine alpha
	 * | '-- container BEGIN
	 * |   +-- test 00 [OK]
	 * |   '-- test 01 [OK]
	 * '-- engine omega
	 *   +-- container END
	 *   | +-- test 10 [OK]
	 *   | '-- test 11 [A] aborted
	 *   '-- container FINAL
	 *     +-- skipped [S] because
	 *     '-- failing [X] BäMM
	 * 
*/ ASCII(".", "| ", "+--", "'--", "[OK]", "[A]", "[X]", "[S]"), /** * Unicode (extended ASCII) characters are used to display the test execution tree. * *

Example test plan execution tree: *

	 * ├─ engine alpha ✔
	 * │  └─ container BEGIN ✔
	 * │     ├─ test 00 ✔
	 * │     └─ test 01 ✔
	 * └─ engine omega ✔
	 *    ├─ container END ✔
	 *    │  ├─ test 10 ✔
	 *    │  └─ test 11 ■ aborted
	 *    └─ container FINAL ✔
	 *       ├─ skipped ↷ because
	 *       └─ failing ✘ BäMM
	 * 
*/ UNICODE("╷", "│ ", "├─", "└─", "✔", "■", "✘", "↷"); public static Theme valueOf(Charset charset) { if (StandardCharsets.UTF_8.equals(charset)) { return UNICODE; } return ASCII; } private final String[] tiles; private final String blank; Theme(String... tiles) { this.tiles = tiles; this.blank = new String(new char[vertical().length()]).replace('\0', ' '); } public final String root() { return tiles[0]; } public final String vertical() { return tiles[1]; } public final String blank() { return blank; } public final String entry() { return tiles[2]; } public final String end() { return tiles[3]; } public final String successful() { return tiles[4]; } public final String aborted() { return tiles[5]; } public final String failed() { return tiles[6]; } public final String skipped() { return tiles[7]; } public final String status(TestExecutionResult result) { switch (result.getStatus()) { case SUCCESSFUL: return successful(); case ABORTED: return aborted(); case FAILED: return failed(); default: return result.getStatus().name(); } } /** * Return lower case {@link #name()} for easier usage in help text for * available options. */ @Override public final String toString() { return name().toLowerCase(); } } package-info.java000066400000000000000000000001541455764576500343070ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/options/** * Configuration options for JUnit's console launcher. */ package org.junit.platform.console.options; junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/package-info.java000066400000000000000000000001531455764576500326720ustar00rootroot00000000000000/** * Support for launching the JUnit Platform from the console. */ package org.junit.platform.console; junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/000077500000000000000000000000001455764576500306315ustar00rootroot00000000000000ColorPalette.java000066400000000000000000000104441455764576500340150ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.nio.file.Path; import java.util.Arrays; import java.util.EnumMap; import java.util.Map; import java.util.Properties; import java.util.function.Function; import java.util.stream.Collectors; /** * @since 1.9 */ class ColorPalette { public static final ColorPalette SINGLE_COLOR = new ColorPalette(singleColorPalette(), false); public static final ColorPalette DEFAULT = new ColorPalette(defaultPalette(), false); public static final ColorPalette NONE = new ColorPalette(new EnumMap<>(Style.class), true); private final Map colorsToAnsiSequences; private final boolean disableAnsiColors; // https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters private static Map defaultPalette() { Map colorsToAnsiSequences = new EnumMap<>(Style.class); colorsToAnsiSequences.put(Style.NONE, "0"); colorsToAnsiSequences.put(Style.SUCCESSFUL, "32"); colorsToAnsiSequences.put(Style.ABORTED, "33"); colorsToAnsiSequences.put(Style.FAILED, "31"); colorsToAnsiSequences.put(Style.SKIPPED, "35"); colorsToAnsiSequences.put(Style.CONTAINER, "36"); colorsToAnsiSequences.put(Style.TEST, "34"); colorsToAnsiSequences.put(Style.DYNAMIC, "35"); colorsToAnsiSequences.put(Style.REPORTED, "37"); return colorsToAnsiSequences; } private static Map singleColorPalette() { Map colorsToAnsiSequences = new EnumMap<>(Style.class); colorsToAnsiSequences.put(Style.NONE, "0"); colorsToAnsiSequences.put(Style.SUCCESSFUL, "1"); colorsToAnsiSequences.put(Style.ABORTED, "4"); colorsToAnsiSequences.put(Style.FAILED, "7"); colorsToAnsiSequences.put(Style.SKIPPED, "9"); colorsToAnsiSequences.put(Style.CONTAINER, "1"); colorsToAnsiSequences.put(Style.TEST, "0"); colorsToAnsiSequences.put(Style.DYNAMIC, "0"); colorsToAnsiSequences.put(Style.REPORTED, "2"); return colorsToAnsiSequences; } public ColorPalette(Map overrides) { this(defaultPalette(), false); if (overrides.containsKey(Style.NONE)) { throw new IllegalArgumentException("Cannot override the standard style 'NONE'"); } this.colorsToAnsiSequences.putAll(overrides); } public ColorPalette(Properties properties) { this(toOverrideMap(properties)); } public ColorPalette(Reader reader) { this(getProperties(reader)); } public ColorPalette(Path path) { this(getProperties(path)); } private ColorPalette(Map colorsToAnsiSequences, boolean disableAnsiColors) { this.colorsToAnsiSequences = colorsToAnsiSequences; this.disableAnsiColors = disableAnsiColors; } private static Map toOverrideMap(Properties properties) { Map upperCaseProperties = properties.entrySet().stream().collect( Collectors.toMap(entry -> ((String) entry.getKey()).toUpperCase(), entry -> (String) entry.getValue())); return Arrays.stream(Style.values()).filter(style -> upperCaseProperties.containsKey(style.name())).collect( Collectors.toMap(Function.identity(), style -> upperCaseProperties.get(style.name()))); } private static Properties getProperties(Reader reader) { Properties properties = new Properties(); try { properties.load(reader); } catch (IOException e) { throw new IllegalArgumentException("Could not read color palette properties", e); } return properties; } private static Properties getProperties(Path path) { try (FileReader fileReader = new FileReader(path.toFile())) { return getProperties(fileReader); } catch (IOException e) { throw new IllegalArgumentException("Could not open color palette properties file", e); } } public String paint(Style style, String text) { return this.disableAnsiColors || style == Style.NONE ? text : getAnsiFormatter(style) + text + getAnsiFormatter(Style.NONE); } private String getAnsiFormatter(Style style) { return String.format("\u001B[%sm", this.colorsToAnsiSequences.get(style)); } } ConsoleTestExecutor.java000066400000000000000000000162371455764576500354070ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.PrintWriter; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import java.util.EnumSet; import java.util.List; import java.util.Optional; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.console.options.Details; import org.junit.platform.console.options.TestConsoleOutputOptions; import org.junit.platform.console.options.TestDiscoveryOptions; import org.junit.platform.console.options.Theme; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.platform.launcher.listeners.SummaryGeneratingListener; import org.junit.platform.launcher.listeners.TestExecutionSummary; import org.junit.platform.reporting.legacy.xml.LegacyXmlReportGeneratingListener; /** * @since 1.0 */ @API(status = INTERNAL, since = "1.0") public class ConsoleTestExecutor { private final TestDiscoveryOptions discoveryOptions; private final TestConsoleOutputOptions outputOptions; private final Supplier launcherSupplier; public ConsoleTestExecutor(TestDiscoveryOptions discoveryOptions, TestConsoleOutputOptions outputOptions) { this(discoveryOptions, outputOptions, LauncherFactory::create); } // for tests only ConsoleTestExecutor(TestDiscoveryOptions discoveryOptions, TestConsoleOutputOptions outputOptions, Supplier launcherSupplier) { this.discoveryOptions = discoveryOptions; this.outputOptions = outputOptions; this.launcherSupplier = launcherSupplier; } public void discover(PrintWriter out) { new CustomContextClassLoaderExecutor(createCustomClassLoader()).invoke(() -> { discoverTests(out); return null; }); } public TestExecutionSummary execute(PrintWriter out, Optional reportsDir) { return new CustomContextClassLoaderExecutor(createCustomClassLoader()) // .invoke(() -> executeTests(out, reportsDir)); } private void discoverTests(PrintWriter out) { Launcher launcher = launcherSupplier.get(); Optional commandLineTestPrinter = createDetailsPrintingListener(out); LauncherDiscoveryRequest discoveryRequest = new DiscoveryRequestCreator().toDiscoveryRequest(discoveryOptions); TestPlan testPlan = launcher.discover(discoveryRequest); commandLineTestPrinter.ifPresent(printer -> printer.listTests(testPlan)); if (outputOptions.getDetails() != Details.NONE) { printFoundTestsSummary(out, testPlan); } } private static void printFoundTestsSummary(PrintWriter out, TestPlan testPlan) { SummaryGeneratingListener summaryListener = new SummaryGeneratingListener(); summaryListener.testPlanExecutionStarted(testPlan); TestExecutionSummary summary = summaryListener.getSummary(); out.printf("%n[%10d containers found ]%n[%10d tests found ]%n%n", summary.getContainersFoundCount(), summary.getTestsFoundCount()); out.flush(); } private TestExecutionSummary executeTests(PrintWriter out, Optional reportsDir) { Launcher launcher = launcherSupplier.get(); SummaryGeneratingListener summaryListener = registerListeners(out, reportsDir, launcher); LauncherDiscoveryRequest discoveryRequest = new DiscoveryRequestCreator().toDiscoveryRequest(discoveryOptions); launcher.execute(discoveryRequest); TestExecutionSummary summary = summaryListener.getSummary(); if (summary.getTotalFailureCount() > 0 || outputOptions.getDetails() != Details.NONE) { printSummary(summary, out); } return summary; } private Optional createCustomClassLoader() { List additionalClasspathEntries = discoveryOptions.getExistingAdditionalClasspathEntries(); if (!additionalClasspathEntries.isEmpty()) { URL[] urls = additionalClasspathEntries.stream().map(this::toURL).toArray(URL[]::new); ClassLoader parentClassLoader = ClassLoaderUtils.getDefaultClassLoader(); ClassLoader customClassLoader = URLClassLoader.newInstance(urls, parentClassLoader); return Optional.of(customClassLoader); } return Optional.empty(); } private URL toURL(Path path) { try { return path.toUri().toURL(); } catch (Exception ex) { throw new JUnitException("Invalid classpath entry: " + path, ex); } } private SummaryGeneratingListener registerListeners(PrintWriter out, Optional reportsDir, Launcher launcher) { // always register summary generating listener SummaryGeneratingListener summaryListener = new SummaryGeneratingListener(); launcher.registerTestExecutionListeners(summaryListener); // optionally, register test plan execution details printing listener createDetailsPrintingListener(out).ifPresent(launcher::registerTestExecutionListeners); // optionally, register XML reports writing listener createXmlWritingListener(out, reportsDir).ifPresent(launcher::registerTestExecutionListeners); return summaryListener; } private Optional createDetailsPrintingListener(PrintWriter out) { ColorPalette colorPalette = getColorPalette(); Theme theme = outputOptions.getTheme(); switch (outputOptions.getDetails()) { case SUMMARY: // summary listener is always created and registered return Optional.empty(); case FLAT: return Optional.of(new FlatPrintingListener(out, colorPalette)); case TREE: return Optional.of(new TreePrintingListener(out, colorPalette, theme)); case VERBOSE: return Optional.of(new VerboseTreePrintingListener(out, colorPalette, 16, theme)); case TESTFEED: return Optional.of(new TestFeedPrintingListener(out, colorPalette)); default: return Optional.empty(); } } private ColorPalette getColorPalette() { if (outputOptions.isAnsiColorOutputDisabled()) { return ColorPalette.NONE; } if (outputOptions.getColorPalettePath() != null) { return new ColorPalette(outputOptions.getColorPalettePath()); } if (outputOptions.isSingleColorPalette()) { return ColorPalette.SINGLE_COLOR; } return ColorPalette.DEFAULT; } private Optional createXmlWritingListener(PrintWriter out, Optional reportsDir) { return reportsDir.map(it -> new LegacyXmlReportGeneratingListener(it, out)); } private void printSummary(TestExecutionSummary summary, PrintWriter out) { // Otherwise the failures have already been printed in detail if (EnumSet.of(Details.NONE, Details.SUMMARY, Details.TREE).contains(outputOptions.getDetails())) { summary.printFailuresTo(out); } summary.printTo(out); } @FunctionalInterface public interface Factory { ConsoleTestExecutor create(TestDiscoveryOptions discoveryOptions, TestConsoleOutputOptions outputOptions); } } CustomContextClassLoaderExecutor.java000066400000000000000000000032761455764576500401000ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.util.Optional; import java.util.function.Supplier; import org.junit.platform.commons.JUnitException; /** * @since 1.0 */ class CustomContextClassLoaderExecutor { private final Optional customClassLoader; CustomContextClassLoaderExecutor(Optional customClassLoader) { this.customClassLoader = customClassLoader; } T invoke(Supplier supplier) { if (customClassLoader.isPresent()) { // Only get/set context class loader when necessary to prevent problems with // security managers return replaceThreadContextClassLoaderAndInvoke(customClassLoader.get(), supplier); } return supplier.get(); } private T replaceThreadContextClassLoaderAndInvoke(ClassLoader customClassLoader, Supplier supplier) { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(customClassLoader); return supplier.get(); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); if (customClassLoader instanceof AutoCloseable) { close((AutoCloseable) customClassLoader); } } } private static void close(AutoCloseable customClassLoader) { try { customClassLoader.close(); } catch (Exception e) { throw new JUnitException("Failed to close custom class loader", e); } } } DetailsPrintingListener.java000066400000000000000000000014401455764576500362220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.util.regex.Pattern; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; interface DetailsPrintingListener extends TestExecutionListener { Pattern LINE_START_PATTERN = Pattern.compile("(?m)^"); void listTests(TestPlan testPlan); static String indented(String message, String indentation) { return LINE_START_PATTERN.matcher(message).replaceAll(indentation).trim(); } } DiscoveryRequestCreator.java000066400000000000000000000137551455764576500362700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.platform.engine.discovery.ClassNameFilter.excludeClassNamePatterns; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModules; import static org.junit.platform.engine.discovery.PackageNameFilter.excludePackageNames; import static org.junit.platform.engine.discovery.PackageNameFilter.includePackageNames; import static org.junit.platform.launcher.EngineFilter.excludeEngines; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.TagFilter.excludeTags; import static org.junit.platform.launcher.TagFilter.includeTags; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.nio.file.Path; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Stream; import org.junit.platform.commons.util.ModuleUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.console.options.TestDiscoveryOptions; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; /** * @since 1.0 */ class DiscoveryRequestCreator { LauncherDiscoveryRequest toDiscoveryRequest(TestDiscoveryOptions options) { LauncherDiscoveryRequestBuilder requestBuilder = request(); List selectors = createDiscoverySelectors(options); requestBuilder.selectors(selectors); addFilters(requestBuilder, options, selectors); requestBuilder.configurationParameters(options.getConfigurationParameters()); return requestBuilder.build(); } private List createDiscoverySelectors(TestDiscoveryOptions options) { List explicitSelectors = options.getExplicitSelectors(); if (options.isScanClasspath()) { Preconditions.condition(explicitSelectors.isEmpty(), "Scanning the classpath and using explicit selectors at the same time is not supported"); return createClasspathRootSelectors(options); } if (options.isScanModulepath()) { Preconditions.condition(explicitSelectors.isEmpty(), "Scanning the module-path and using explicit selectors at the same time is not supported"); return selectModules(ModuleUtils.findAllNonSystemBootModuleNames()); } return Preconditions.notEmpty(explicitSelectors, "Please specify an explicit selector option or use --scan-class-path or --scan-modules"); } private List createClasspathRootSelectors(TestDiscoveryOptions options) { Set classpathRoots = determineClasspathRoots(options); return selectClasspathRoots(classpathRoots); } private Set determineClasspathRoots(TestDiscoveryOptions options) { if (options.getSelectedClasspathEntries().isEmpty()) { Set rootDirs = new LinkedHashSet<>(ReflectionUtils.getAllClasspathRootDirectories()); rootDirs.addAll(options.getExistingAdditionalClasspathEntries()); return rootDirs; } return new LinkedHashSet<>(options.getSelectedClasspathEntries()); } private void addFilters(LauncherDiscoveryRequestBuilder requestBuilder, TestDiscoveryOptions options, List selectors) { requestBuilder.filters(includedClassNamePatterns(options, selectors)); if (!options.getExcludedClassNamePatterns().isEmpty()) { requestBuilder.filters( excludeClassNamePatterns(options.getExcludedClassNamePatterns().toArray(new String[0]))); } if (!options.getIncludedPackages().isEmpty()) { requestBuilder.filters(includePackageNames(options.getIncludedPackages())); } if (!options.getExcludedPackages().isEmpty()) { requestBuilder.filters(excludePackageNames(options.getExcludedPackages())); } if (!options.getIncludedTagExpressions().isEmpty()) { requestBuilder.filters(includeTags(options.getIncludedTagExpressions())); } if (!options.getExcludedTagExpressions().isEmpty()) { requestBuilder.filters(excludeTags(options.getExcludedTagExpressions())); } if (!options.getIncludedEngines().isEmpty()) { requestBuilder.filters(includeEngines(options.getIncludedEngines())); } if (!options.getExcludedEngines().isEmpty()) { requestBuilder.filters(excludeEngines(options.getExcludedEngines())); } } private ClassNameFilter includedClassNamePatterns(TestDiscoveryOptions options, List selectors) { Stream patternStreams = Stream.concat( // options.getIncludedClassNamePatterns().stream(), // selectors.stream() // .map(selector -> selector instanceof IterationSelector ? ((IterationSelector) selector).getParentSelector() : selector) // .map(selector -> { if (selector instanceof ClassSelector) { return ((ClassSelector) selector).getClassName(); } if (selector instanceof MethodSelector) { return ((MethodSelector) selector).getClassName(); } return null; }) // .filter(Objects::nonNull) // .map(Pattern::quote)); return includeClassNamePatterns(patternStreams.toArray(String[]::new)); } } FlatPrintingListener.java000066400000000000000000000072351455764576500355330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.io.PrintWriter; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class FlatPrintingListener implements DetailsPrintingListener { static final String INDENTATION = " "; private final PrintWriter out; private final ColorPalette colorPalette; FlatPrintingListener(PrintWriter out, ColorPalette colorPalette) { this.out = out; this.colorPalette = colorPalette; } @Override public void testPlanExecutionStarted(TestPlan testPlan) { this.out.printf("Test execution started. Number of static tests: %d%n", testPlan.countTestIdentifiers(TestIdentifier::isTest)); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { this.out.println("Test execution finished."); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { printlnTestDescriptor(Style.DYNAMIC, "Registered:", testIdentifier); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { printlnTestDescriptor(Style.SKIPPED, "Skipped:", testIdentifier); printlnMessage(Style.SKIPPED, "Reason", reason); } @Override public void executionStarted(TestIdentifier testIdentifier) { printlnTestDescriptor(Style.valueOf(testIdentifier), "Started:", testIdentifier); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { Style style = Style.valueOf(testExecutionResult); printlnTestDescriptor(style, "Finished:", testIdentifier); testExecutionResult.getThrowable().ifPresent(t -> printlnException(style, t)); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { printlnTestDescriptor(Style.REPORTED, "Reported:", testIdentifier); printlnMessage(Style.REPORTED, "Reported values", entry.toString()); } private void printlnTestDescriptor(Style style, String message, TestIdentifier testIdentifier) { println(style, "%-10s %s (%s)", message, testIdentifier.getDisplayName(), testIdentifier.getUniqueId()); } private void printlnException(Style style, Throwable throwable) { printlnMessage(style, "Exception", ExceptionUtils.readStackTrace(throwable)); } private void printlnMessage(Style style, String message, String detail) { println(style, INDENTATION + "=> " + message + ": %s", indented(detail)); } private void println(Style style, String format, Object... args) { this.out.println(colorPalette.paint(style, String.format(format, args))); } /** * Indent the given message if it is a multi-line string. * *

{@link #INDENTATION} is used to prefix the start of each new line * except the first one. * * @param message the message to indent * @return indented message */ private static String indented(String message) { return DetailsPrintingListener.indented(message, INDENTATION); } @Override public void listTests(TestPlan testPlan) { testPlan.accept(new TestPlan.Visitor() { @Override public void visit(TestIdentifier testIdentifier) { println(Style.valueOf(testIdentifier), "%s (%s)", testIdentifier.getDisplayName(), testIdentifier.getUniqueId()); } }); } } junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/Style.java000066400000000000000000000017011455764576500325730ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestIdentifier; /** * @since 1.9 */ enum Style { NONE, SUCCESSFUL, ABORTED, FAILED, SKIPPED, CONTAINER, TEST, DYNAMIC, REPORTED; static Style valueOf(TestExecutionResult result) { switch (result.getStatus()) { case SUCCESSFUL: return Style.SUCCESSFUL; case ABORTED: return Style.ABORTED; case FAILED: return Style.FAILED; default: return Style.NONE; } } static Style valueOf(TestIdentifier testIdentifier) { return testIdentifier.isContainer() ? CONTAINER : TEST; } } TestFeedPrintingListener.java000066400000000000000000000101161455764576500363400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; class TestFeedPrintingListener implements DetailsPrintingListener { private static final String INDENTATION = "\t"; private static final String STATUS_SEPARATOR = " :: "; private final PrintWriter out; private final ColorPalette colorPalette; private TestPlan testPlan; TestFeedPrintingListener(PrintWriter out, ColorPalette colorPalette) { this.out = out; this.colorPalette = colorPalette; } @Override public void testPlanExecutionStarted(TestPlan testPlan) { this.testPlan = testPlan; } @Override public void testPlanExecutionFinished(TestPlan testPlan) { this.testPlan = null; } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { if (shouldPrint(testIdentifier)) { String msg = formatTestIdentifier(testIdentifier); String indentedReason = indented(String.format("Reason: %s", reason)); println(Style.SKIPPED, String.format("%s" + STATUS_SEPARATOR + "SKIPPED%n" + INDENTATION + "%s", msg, indentedReason)); } } @Override public void executionStarted(TestIdentifier testIdentifier) { if (shouldPrint(testIdentifier)) { String msg = formatTestIdentifier(testIdentifier); println(Style.NONE, String.format("%s" + STATUS_SEPARATOR + "STARTED", msg)); } } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { TestExecutionResult.Status status = testExecutionResult.getStatus(); if (testExecutionResult.getThrowable().isPresent()) { Style style = Style.valueOf(testExecutionResult); String msg = formatTestIdentifier(testIdentifier); Throwable throwable = testExecutionResult.getThrowable().get(); String stacktrace = indented(ExceptionUtils.readStackTrace(throwable)); println(style, String.format("%s" + STATUS_SEPARATOR + "%s%n" + INDENTATION + "%s", msg, status, stacktrace)); } else if (shouldPrint(testIdentifier) || testExecutionResult.getStatus() != SUCCESSFUL) { Style style = Style.valueOf(testExecutionResult); String msg = formatTestIdentifier(testIdentifier); println(style, String.format("%s" + STATUS_SEPARATOR + "%s", msg, status)); } } private String formatTestIdentifier(TestIdentifier testIdentifier) { return String.join(" > ", collectDisplayNames(testIdentifier.getUniqueIdObject())); } private void println(Style style, String message) { this.out.println(colorPalette.paint(style, message)); } private List collectDisplayNames(UniqueId uniqueId) { int size = uniqueId.getSegments().size(); List displayNames = new ArrayList<>(size); for (int i = 0; i < size; i++) { displayNames.add(0, testPlan.getTestIdentifier(uniqueId).getDisplayName()); if (i < size - 1) { uniqueId = uniqueId.removeLastSegment(); } } return displayNames; } private static String indented(String message) { return DetailsPrintingListener.indented(message, INDENTATION); } @Override public void listTests(TestPlan testPlan) { this.testPlan = testPlan; try { testPlan.accept(new TestPlan.Visitor() { @Override public void visit(TestIdentifier testIdentifier) { if (shouldPrint(testIdentifier)) { println(Style.NONE, formatTestIdentifier(testIdentifier)); } } }); } finally { this.testPlan = null; } } private static boolean shouldPrint(TestIdentifier testIdentifier) { return testIdentifier.isTest(); } } junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java000066400000000000000000000044641455764576500332110ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.util.Optional; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; /** * @since 1.0 */ class TreeNode { private final String caption; private final long creation; long duration; private String reason; private TestIdentifier identifier; private TestExecutionResult result; final Queue reports = new ConcurrentLinkedQueue<>(); final Queue children = new ConcurrentLinkedQueue<>(); boolean visible; TreeNode(String caption) { this.caption = caption; this.creation = System.currentTimeMillis(); this.visible = false; } TreeNode(TestIdentifier identifier) { this(createCaption(identifier.getDisplayName())); this.identifier = identifier; this.visible = true; } TreeNode(TestIdentifier identifier, String reason) { this(identifier); this.reason = reason; } TreeNode addChild(TreeNode node) { children.add(node); return this; } TreeNode addReportEntry(ReportEntry reportEntry) { reports.add(reportEntry); return this; } TreeNode setResult(TestExecutionResult result) { this.result = result; this.duration = System.currentTimeMillis() - creation; return this; } public String caption() { return caption; } Optional reason() { return Optional.ofNullable(reason); } Optional result() { return Optional.ofNullable(result); } Optional identifier() { return Optional.ofNullable(identifier); } static String createCaption(String displayName) { boolean normal = displayName.length() <= 80; String caption = normal ? displayName : displayName.substring(0, 80) + "..."; String whites = StringUtils.replaceWhitespaceCharacters(caption, " "); return StringUtils.replaceIsoControlCharacters(whites, "."); } } TreePrinter.java000066400000000000000000000124641455764576500336670ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import java.io.PrintWriter; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.engine.reporting.ReportEntry; /** * @since 1.0 */ class TreePrinter { private final PrintWriter out; private final Theme theme; private final ColorPalette colorPalette; TreePrinter(PrintWriter out, Theme theme, ColorPalette colorPalette) { this.out = out; this.theme = theme; this.colorPalette = colorPalette; } void print(TreeNode node) { out.println(color(Style.CONTAINER, theme.root())); print(node, "", true); out.flush(); } private void print(TreeNode node, String indent, boolean continuous) { if (node.visible) { printVisible(node, indent, continuous); } if (node.children.isEmpty()) { return; } if (node.visible) { indent += continuous ? theme.vertical() : theme.blank(); } Iterator iterator = node.children.iterator(); while (iterator.hasNext()) { print(iterator.next(), indent, iterator.hasNext()); } } private void printVisible(TreeNode node, String indent, boolean continuous) { String bullet = continuous ? theme.entry() : theme.end(); String prefix = color(Style.CONTAINER, indent + bullet); String tabbed = color(Style.CONTAINER, indent + tab(node, continuous)); String caption = colorCaption(node); String duration = color(Style.CONTAINER, node.duration + " ms"); String icon = color(Style.SKIPPED, theme.skipped()); if (node.result().isPresent()) { TestExecutionResult result = node.result().get(); Style resultStyle = Style.valueOf(result); icon = color(resultStyle, theme.status(result)); } out.print(prefix); out.print(" "); out.print(caption); if (node.duration > 10000 && node.children.isEmpty()) { out.print(" "); out.print(duration); } boolean nodeIsBeingListed = node.duration == 0 && !node.result().isPresent() && !node.reason().isPresent(); if (!nodeIsBeingListed) { out.print(" "); out.print(icon); } node.result().ifPresent(result -> printThrowable(tabbed, result)); node.reason().ifPresent(reason -> printMessage(Style.SKIPPED, tabbed, reason)); node.reports.forEach(e -> printReportEntry(tabbed, e)); out.println(); } private String tab(TreeNode node, boolean continuous) { // We might be the "last" node in this level, that means // `continuous == false`, but still need to include a vertical // bar for printing stack traces, messages and reports. // See https://github.com/junit-team/junit5/issues/1531 if (node.children.size() > 0) { return theme.blank() + theme.vertical(); } return (continuous ? theme.vertical() : theme.blank()) + theme.blank(); } private String colorCaption(TreeNode node) { String caption = node.caption(); if (node.result().isPresent()) { TestExecutionResult result = node.result().get(); Style resultStyle = Style.valueOf(result); if (result.getStatus() != Status.SUCCESSFUL) { return color(resultStyle, caption); } } if (node.reason().isPresent()) { return color(Style.SKIPPED, caption); } Style style = node.identifier().map(Style::valueOf).orElse(Style.NONE); return color(style, caption); } private void printThrowable(String indent, TestExecutionResult result) { if (!result.getThrowable().isPresent()) { return; } Throwable throwable = result.getThrowable().get(); String message = throwable.getMessage(); if (StringUtils.isBlank(message)) { message = throwable.toString(); } printMessage(Style.FAILED, indent, message); } private void printReportEntry(String indent, ReportEntry reportEntry) { out.println(); out.print(indent); out.print(reportEntry.getTimestamp()); Set> entries = reportEntry.getKeyValuePairs().entrySet(); if (entries.size() == 1) { printReportEntry(" ", getOnlyElement(entries)); return; } for (Map.Entry entry : entries) { out.println(); printReportEntry(indent + theme.blank(), entry); } } private void printReportEntry(String indent, Map.Entry mapEntry) { out.print(indent); out.print(color(Style.ABORTED, mapEntry.getKey())); out.print(" = `"); out.print(color(Style.SUCCESSFUL, mapEntry.getValue())); out.print("`"); } private void printMessage(Style style, String indent, String message) { String[] lines = message.split("\\R"); out.print(" "); out.print(color(style, lines[0])); if (lines.length > 1) { for (int i = 1; i < lines.length; i++) { out.println(); out.print(indent); if (StringUtils.isNotBlank(lines[i])) { String extra = theme.blank(); out.print(color(style, extra + lines[i])); } } } } private String color(Style style, String text) { return colorPalette.paint(style, text); } } TreePrintingListener.java000066400000000000000000000051371455764576500355430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import java.io.PrintWriter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class TreePrintingListener implements DetailsPrintingListener { private final Map nodesByUniqueId = new ConcurrentHashMap<>(); private TreeNode root; private final TreePrinter treePrinter; TreePrintingListener(PrintWriter out, ColorPalette colorPalette, Theme theme) { this.treePrinter = new TreePrinter(out, theme, colorPalette); } private void addNode(TestIdentifier testIdentifier, TreeNode node) { nodesByUniqueId.put(testIdentifier.getUniqueIdObject(), node); testIdentifier.getParentIdObject().map(nodesByUniqueId::get).orElse(root).addChild(node); } private TreeNode getNode(TestIdentifier testIdentifier) { return nodesByUniqueId.get(testIdentifier.getUniqueIdObject()); } @Override public void testPlanExecutionStarted(TestPlan testPlan) { root = new TreeNode(testPlan.toString()); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { treePrinter.print(root); } @Override public void executionStarted(TestIdentifier testIdentifier) { addNode(testIdentifier, new TreeNode(testIdentifier)); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { getNode(testIdentifier).setResult(testExecutionResult); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { addNode(testIdentifier, new TreeNode(testIdentifier, reason)); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { getNode(testIdentifier).addReportEntry(entry); } @Override public void listTests(TestPlan testPlan) { root = new TreeNode(testPlan.toString()); testPlan.accept(new TestPlan.Visitor() { @Override public void visit(TestIdentifier testIdentifier) { addNode(testIdentifier, new TreeNode(testIdentifier)); } }); treePrinter.print(root); } } VerboseTreePrintingListener.java000066400000000000000000000165251455764576500370740ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.platform.commons.util.ExceptionUtils.readStackTrace; import static org.junit.platform.console.tasks.Style.NONE; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.Deque; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class VerboseTreePrintingListener implements DetailsPrintingListener { private final PrintWriter out; private final Theme theme; private final ColorPalette colorPalette; private final Deque frames; private final String[] verticals; private long executionStartedMillis; VerboseTreePrintingListener(PrintWriter out, ColorPalette colorPalette, int maxContainerNestingLevel, Theme theme) { this.out = out; this.colorPalette = colorPalette; this.theme = theme; // create frame stack and push initial root frame this.frames = new ArrayDeque<>(); this.frames.push(0L); // create and populate vertical indentation lookup table this.verticals = new String[Math.max(10, maxContainerNestingLevel) + 1]; this.verticals[0] = ""; // no frame this.verticals[1] = ""; // synthetic root "/" level this.verticals[2] = ""; // "engine" level for (int i = 3; i < verticals.length; i++) { verticals[i] = verticals[i - 1] + theme.vertical(); } } @Override public void testPlanExecutionStarted(TestPlan testPlan) { frames.push(System.currentTimeMillis()); String prefix = "Test plan execution started. Number of static tests: "; printNumberOfTests(testPlan, prefix); printf(Style.CONTAINER, "%s%n", theme.root()); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { frames.pop(); printNumberOfTests(testPlan, "Test plan execution finished. Number of all tests: "); } private void printNumberOfTests(TestPlan testPlan, String prefix) { long tests = testPlan.countTestIdentifiers(TestIdentifier::isTest); printf(NONE, "%s", prefix); printf(Style.TEST, "%d%n", tests); } @Override public void executionStarted(TestIdentifier testIdentifier) { this.executionStartedMillis = System.currentTimeMillis(); if (testIdentifier.isContainer()) { printVerticals(theme.entry()); printf(Style.CONTAINER, " %s", testIdentifier.getDisplayName()); printf(NONE, "%n"); frames.push(System.currentTimeMillis()); } if (testIdentifier.isContainer()) { return; } printVerticals(theme.entry()); printf(Style.valueOf(testIdentifier), " %s%n", testIdentifier.getDisplayName()); printDetails(testIdentifier); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { testExecutionResult.getThrowable().ifPresent(t -> printDetail(Style.FAILED, "caught", readStackTrace(t))); if (testIdentifier.isContainer()) { Long creationMillis = frames.pop(); printVerticals(theme.end()); printf(Style.CONTAINER, " %s", testIdentifier.getDisplayName()); printf(NONE, " finished after %d ms.%n", System.currentTimeMillis() - creationMillis); return; } printDetail(NONE, "duration", "%d ms%n", System.currentTimeMillis() - executionStartedMillis); String status = theme.status(testExecutionResult) + " " + testExecutionResult.getStatus(); printDetail(Style.valueOf(testExecutionResult), "status", "%s%n", status); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { printVerticals(theme.entry()); printf(Style.valueOf(testIdentifier), " %s%n", testIdentifier.getDisplayName()); printDetails(testIdentifier); printDetail(Style.SKIPPED, "reason", reason); printDetail(Style.SKIPPED, "status", theme.skipped() + " SKIPPED"); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { printVerticals(theme.entry()); printf(Style.DYNAMIC, " %s", testIdentifier.getDisplayName()); printf(NONE, "%s%n", " dynamically registered"); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { printDetail(Style.REPORTED, "reports", entry.toString()); } /** * Print static information about the test identifier. */ private void printDetails(TestIdentifier testIdentifier) { printDetail(NONE, "tags", "%s%n", testIdentifier.getTags()); printDetail(NONE, "uniqueId", "%s%n", testIdentifier.getUniqueId()); printDetail(NONE, "parent", "%s%n", testIdentifier.getParentId().orElse("[]")); testIdentifier.getSource().ifPresent(source -> printDetail(NONE, "source", "%s%n", source)); } private String verticals() { return verticals(frames.size()); } private String verticals(int index) { return verticals[Math.min(index, verticals.length - 1)]; } private void printVerticals(String tile) { printf(NONE, verticals()); printf(NONE, tile); } private void printf(Style style, String message, Object... args) { out.printf(colorPalette.paint(style, message), args); out.flush(); } /** * Print single detail with a potential multi-line message. */ private void printDetail(Style style, String detail, String format, Object... args) { // print initial verticals - expecting to be at start of the line String verticals = verticals(frames.size() + 1); printf(NONE, verticals); String detailFormat = "%9s"; // omit detail string if it's empty if (!detail.isEmpty()) { printf(NONE, "%s", String.format(detailFormat + ": ", detail)); } // trivial case: at least one arg is given? Let printf do the entire work if (args.length > 0) { printf(style, format, args); return; } // still here? Split format into separate lines and indent them from the second line on String[] lines = format.split("\\R"); printf(style, "%s", lines[0]); if (lines.length > 1) { String delimiter = System.lineSeparator() + verticals + String.format(detailFormat + " ", ""); for (int i = 1; i < lines.length; i++) { printf(NONE, "%s", delimiter); printf(style, "%s", lines[i]); } } printf(NONE, "%n"); } @Override public void listTests(TestPlan testPlan) { frames.push(0L); testPlan.accept(new TestPlan.Visitor() { @Override public void preVisitContainer(TestIdentifier testIdentifier) { if (!testPlan.getChildren(testIdentifier).isEmpty()) { printVerticals(theme.entry()); printf(Style.CONTAINER, " %s", testIdentifier.getDisplayName()); printf(NONE, "%n"); frames.push(0L); } } @Override public void visit(TestIdentifier testIdentifier) { if (testPlan.getChildren(testIdentifier).isEmpty()) { printVerticals(theme.entry()); printf(Style.valueOf(testIdentifier), " %s%n", testIdentifier.getDisplayName()); printDetails(testIdentifier); } } @Override public void postVisitContainer(TestIdentifier testIdentifier) { if (!testPlan.getChildren(testIdentifier).isEmpty()) { frames.pop(); printVerticals(theme.end()); printf(Style.CONTAINER, " %s%n", testIdentifier.getDisplayName()); } } }); frames.pop(); } } package-info.java000066400000000000000000000001551455764576500337420ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java/org/junit/platform/console/tasks/** * Internal execution tasks for JUnit's console launcher. */ package org.junit.platform.console.tasks; junit5-r5.10.2/junit-platform-console/src/main/java17/000077500000000000000000000000001455764576500224465ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/000077500000000000000000000000001455764576500232355ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/junit/000077500000000000000000000000001455764576500243665ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/junit/platform/000077500000000000000000000000001455764576500262125ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/junit/platform/console/000077500000000000000000000000001455764576500276545ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/junit/platform/console/options/000077500000000000000000000000001455764576500313475ustar00rootroot00000000000000ConsoleUtils.java000066400000000000000000000021071455764576500345560ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java17/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.Console; import java.nio.charset.Charset; import org.apiguardian.api.API; /** * Collection of utilities for working with {@code java.io.Console} * and friends. * *

DISCLAIMER

* *

These utilities are intended solely for usage within the JUnit framework * itself. Any usage by external parties is not supported. * Use at your own risk! * * @since 1.9 */ @API(status = INTERNAL, since = "1.9") public class ConsoleUtils { /** * {@return the charset of the console} */ public static Charset charset() { Console console = System.console(); return console != null ? console.charset() : Charset.defaultCharset(); } } junit5-r5.10.2/junit-platform-console/src/main/java9/000077500000000000000000000000001455764576500223675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java9/org/000077500000000000000000000000001455764576500231565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java9/org/junit/000077500000000000000000000000001455764576500243075ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java9/org/junit/platform/000077500000000000000000000000001455764576500261335ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java9/org/junit/platform/console/000077500000000000000000000000001455764576500275755ustar00rootroot00000000000000ConsoleLauncherToolProvider.java000066400000000000000000000015741455764576500360250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/java9/org/junit/platform/console/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static org.apiguardian.api.API.Status.STABLE; import java.io.PrintWriter; import java.util.spi.ToolProvider; import org.apiguardian.api.API; /** * Run the JUnit Platform Console Launcher as a service. * * @since 1.6 */ @API(status = STABLE, since = "1.10") public class ConsoleLauncherToolProvider implements ToolProvider { @Override public String name() { return "junit"; } @Override public int run(PrintWriter out, PrintWriter err, String... args) { return ConsoleLauncher.run(out, err, args).getExitCode(); } } junit5-r5.10.2/junit-platform-console/src/main/resources/000077500000000000000000000000001455764576500233675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/resources/META-INF/000077500000000000000000000000001455764576500245275ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500263525ustar00rootroot00000000000000java.util.spi.ToolProvider000066400000000000000000000000671455764576500333370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/main/resources/META-INF/servicesorg.junit.platform.console.ConsoleLauncherToolProvider junit5-r5.10.2/junit-platform-console/src/module/000077500000000000000000000000001455764576500217165ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/module/org.junit.platform.console/000077500000000000000000000000001455764576500271215ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-console/src/module/org.junit.platform.console/module-info.java000066400000000000000000000014031455764576500322000ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Support for launching the JUnit Platform from the console. * * @since 1.0 * @provides java.util.spi.ToolProvider */ module org.junit.platform.console { requires static org.apiguardian.api; requires org.junit.platform.commons; requires org.junit.platform.engine; requires org.junit.platform.launcher; requires org.junit.platform.reporting; provides java.util.spi.ToolProvider with org.junit.platform.console.ConsoleLauncherToolProvider; } junit5-r5.10.2/junit-platform-engine/000077500000000000000000000000001455764576500174455ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/junit-platform-engine.gradle.kts000066400000000000000000000006161455764576500256460ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") `java-test-fixtures` } description = "JUnit Platform Engine API" dependencies { api(platform(projects.junitBom)) api(libs.opentest4j) api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) testImplementation(libs.assertj) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-engine/src/000077500000000000000000000000001455764576500202345ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/000077500000000000000000000000001455764576500211605ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/000077500000000000000000000000001455764576500221015ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/000077500000000000000000000000001455764576500226705ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/000077500000000000000000000000001455764576500240215ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500256455ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/000077500000000000000000000000001455764576500271125ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java000066400000000000000000000045761455764576500331010ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static java.lang.String.format; import static java.util.stream.Collectors.joining; import static org.junit.platform.engine.FilterResult.included; import java.util.ArrayList; import java.util.Collection; import java.util.function.Predicate; import org.junit.platform.commons.util.Preconditions; /** * Combines a collection of {@link Filter Filters} into a new filter that will * include elements if and only if all of the filters in the specified collection * include it. * * @since 1.0 */ class CompositeFilter implements Filter { @SuppressWarnings("rawtypes") private static final Filter ALWAYS_INCLUDED_FILTER = new Filter() { @Override public FilterResult apply(Object obj) { return ALWAYS_INCLUDED_RESULT; } @Override public Predicate toPredicate() { return obj -> true; } }; private static final FilterResult ALWAYS_INCLUDED_RESULT = included("Always included"); private static final FilterResult INCLUDED_BY_ALL_FILTERS = included("Element was included by all filters."); @SuppressWarnings("unchecked") static Filter alwaysIncluded() { return ALWAYS_INCLUDED_FILTER; } private final Collection> filters; CompositeFilter(Collection> filters) { this.filters = new ArrayList<>(Preconditions.notEmpty(filters, "filters must not be empty")); } @Override public FilterResult apply(T element) { // @formatter:off return filters.stream() .map(filter -> filter.apply(element)) .filter(FilterResult::excluded) .findFirst() .orElse(INCLUDED_BY_ALL_FILTERS); // @formatter:on } @Override public Predicate toPredicate() { // @formatter:off return filters.stream() .map(Filter::toPredicate) .reduce(Predicate::and) .get(); // it's safe to call get() here because the constructor ensures filters is not empty // @formatter:on } @Override public String toString() { // @formatter:off return filters.stream() .map(Object::toString) .map(value -> format("(%s)", value)) .collect(joining(" and ")); // @formatter:on } } ConfigurationParameters.java000066400000000000000000000121271455764576500345340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import java.util.Set; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; /** * Configuration parameters that {@link TestEngine TestEngines} may use to * influence test discovery and execution. * *

For example, the JUnit Jupiter engine uses a configuration parameter to * enable IDEs and build tools to deactivate conditional test execution. * *

As of JUnit Platform 1.8, configuration parameters are also made available to * implementations of the {@link org.junit.platform.launcher.TestExecutionListener} * API via the {@link org.junit.platform.launcher.TestPlan}. * * @since 1.0 * @see TestEngine * @see EngineDiscoveryRequest * @see ExecutionRequest */ @API(status = STABLE, since = "1.0") public interface ConfigurationParameters { /** * Name of the JUnit Platform configuration file: {@value}. * *

If a properties file with this name is present in the root of the * classpath, it will be used as a source for configuration * parameters. If multiple files are present, only the first one * detected in the classpath will be used. * * @see java.util.Properties */ String CONFIG_FILE_NAME = "junit-platform.properties"; /** * Get the configuration parameter stored under the specified {@code key}. * *

If no such key is present in this {@code ConfigurationParameters}, * an attempt will be made to look up the value as a JVM system property. * If no such system property exists, an attempt will be made to look up * the value in the {@linkplain #CONFIG_FILE_NAME JUnit Platform properties * file}. * * @param key the key to look up; never {@code null} or blank * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @see #getBoolean(String) * @see System#getProperty(String) * @see #CONFIG_FILE_NAME */ Optional get(String key); /** * Get the boolean configuration parameter stored under the specified * {@code key}. * *

If no such key is present in this {@code ConfigurationParameters}, * an attempt will be made to look up the value as a JVM system property. * If no such system property exists, an attempt will be made to look up * the value in the {@linkplain #CONFIG_FILE_NAME JUnit Platform properties * file}. * * @param key the key to look up; never {@code null} or blank * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @see #get(String) * @see Boolean#parseBoolean(String) * @see System#getProperty(String) * @see #CONFIG_FILE_NAME */ Optional getBoolean(String key); /** * Get and transform the configuration parameter stored under the specified * {@code key} using the specified {@code transformer}. * *

If no such key is present in this {@code ConfigurationParameters}, * an attempt will be made to look up the value as a JVM system property. * If no such system property exists, an attempt will be made to look up * the value in the {@linkplain #CONFIG_FILE_NAME JUnit Platform properties * file}. * *

In case the transformer throws an exception, it will be wrapped in a * {@link JUnitException} with a helpful message. * * @param key the key to look up; never {@code null} or blank * @param transformer the transformer to apply in case a value is found; * never {@code null} * @return an {@code Optional} containing the value; never {@code null} * but potentially empty * * @since 1.3 * @see #getBoolean(String) * @see System#getProperty(String) * @see #CONFIG_FILE_NAME */ @API(status = STABLE, since = "1.3") default Optional get(String key, Function transformer) { Preconditions.notNull(transformer, "transformer must not be null"); return get(key).map(input -> { try { return transformer.apply(input); } catch (Exception ex) { String message = String.format( "Failed to transform configuration parameter with key '%s' and initial value '%s'", key, input); throw new JUnitException(message, ex); } }); } /** * Get the number of configuration parameters stored directly in this * {@code ConfigurationParameters}. * @deprecated as of JUnit Platform 1.9 in favor of {@link #keySet()} */ @Deprecated @API(status = DEPRECATED, since = "1.9") int size(); /** * Get the keys of all configuration parameters stored in this * {@code ConfigurationParameters}. * * @return the set of keys contained in this {@code ConfigurationParameters} */ @API(status = STABLE, since = "1.9") Set keySet(); } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoveryFilter.java000066400000000000000000000015421455764576500330740ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * A {@link DiscoveryFilter} is applied during test discovery to determine if * a given container or test should be included in the test plan. * *

{@link TestEngine TestEngines} should apply {@code DiscoveryFilters} * during the test discovery phase. * * @since 1.0 * @see EngineDiscoveryRequest * @see TestEngine */ @API(status = STABLE, since = "1.0") public interface DiscoveryFilter extends Filter { } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelector.java000066400000000000000000000014361455764576500334310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * A selector defines what a {@link TestEngine} can use to discover tests * — for example, the name of a Java class, the path to a file or * directory, etc. * * @since 1.0 * @see EngineDiscoveryRequest * @see org.junit.platform.engine.discovery.DiscoverySelectors */ @API(status = STABLE, since = "1.0") public interface DiscoverySelector { } EngineDiscoveryListener.java000066400000000000000000000035051455764576500345040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * {@code EngineDiscoveryListener} contains {@link TestEngine} access to the * information necessary to discover tests and containers. * *

All methods in this interface have empty default implementations. * Concrete implementations may therefore override one or more of these methods * to be notified of the selected events. * *

The methods declared in this interface should be called by * each {@link TestEngine} during test discovery. However, since this interface * was only added in 1.6, older engines might not yet do so. * * @since 1.6 * @see EngineDiscoveryRequest#getDiscoveryListener() */ @API(status = STABLE, since = "1.10") public interface EngineDiscoveryListener { /** * No-op implementation of {@code EngineDiscoveryListener} */ EngineDiscoveryListener NOOP = new EngineDiscoveryListener() { }; /** * Must be called after a discovery selector has been processed by a test * engine. * *

Exceptions thrown by implementations of this method will cause test * discovery of the current engine to be aborted. * * @param engineId the unique ID of the engine descriptor * @param selector the processed selector * @param result the resolution result of the supplied engine and selector * @see SelectorResolutionResult */ default void selectorProcessed(UniqueId engineId, DiscoverySelector selector, SelectorResolutionResult result) { } } EngineDiscoveryRequest.java000066400000000000000000000057131455764576500343520ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import org.apiguardian.api.API; /** * {@code EngineDiscoveryRequest} provides a {@link TestEngine} access to the * information necessary to discover tests and containers. * *

A request is comprised of {@linkplain DiscoverySelector selectors} and * {@linkplain DiscoveryFilter filters}. While the former select * resources that engines can use to discover tests, the latter specify how * such resources are to be filtered. All of the filters * have to include a resource for it to end up in the test plan. * *

In addition, the supplied {@linkplain ConfigurationParameters * configuration parameters} can be used to influence the discovery process. * * @since 1.0 * @see TestEngine * @see TestDescriptor * @see DiscoverySelector * @see DiscoveryFilter * @see ConfigurationParameters */ @API(status = STABLE, since = "1.0") public interface EngineDiscoveryRequest { /** * Get the {@link DiscoverySelector DiscoverySelectors} for this request, * filtered by a particular type. * * @param selectorType the type of {@link DiscoverySelector} to filter by * @return all selectors of this request that are instances of * {@code selectorType}; never {@code null} but potentially empty */ List getSelectorsByType(Class selectorType); /** * Get the {@link DiscoveryFilter DiscoveryFilters} for this request, * filtered by a particular type. * *

The returned filters are to be combined using AND semantics, i.e. all * of them have to include a resource for it to end up in the test plan. * * @param filterType the type of {@link DiscoveryFilter} to filter by * @return all filters of this request that are instances of * {@code filterType}; never {@code null} but potentially empty */ > List getFiltersByType(Class filterType); /** * Get the {@link ConfigurationParameters} for this request. * * @return the configuration parameters; never {@code null} */ ConfigurationParameters getConfigurationParameters(); /** * Get the {@link EngineDiscoveryListener} for this request. * *

The default implementation returns a no-op listener that ignores all * calls so that engines that call this methods can be used with an earlier * version of the JUnit Platform that did not yet include this API. * * @return the discovery listener; never {@code null} * @since 1.6 */ @API(status = STABLE, since = "1.10") default EngineDiscoveryListener getDiscoveryListener() { return EngineDiscoveryListener.NOOP; } } EngineExecutionListener.java000066400000000000000000000116561455764576500345060ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.engine.reporting.ReportEntry; /** * Listener to be notified of test execution events by * {@linkplain TestEngine test engines}. * *

Contrary to JUnit 4, {@linkplain TestEngine test engines} * must report events not only for {@linkplain TestDescriptor test descriptors} * that represent executable leaves but also for all intermediate containers. * * @since 1.0 * @see TestEngine * @see ExecutionRequest */ @API(status = STABLE, since = "1.0") public interface EngineExecutionListener { /** * No-op implementation of {@code EngineExecutionListener} */ EngineExecutionListener NOOP = new EngineExecutionListener() { }; /** * Must be called when a new, dynamic {@link TestDescriptor} has been * registered. * *

A dynamic test is a test that is not known a-priori and * therefore was not present in the test tree when discovering tests. * * @param testDescriptor the descriptor of the newly registered test * or container */ default void dynamicTestRegistered(TestDescriptor testDescriptor) { } /** * Must be called when the execution of a leaf or subtree of the test tree * has been skipped. * *

The {@link TestDescriptor} may represent a test or a container. In the * case of a container, engines must not fire any additional events for its * descendants. * *

A skipped test or subtree of tests must not be reported as * {@linkplain #executionStarted started} or * {@linkplain #executionFinished finished}. * * @param testDescriptor the descriptor of the skipped test or container * @param reason a human-readable message describing why the execution * has been skipped */ default void executionSkipped(TestDescriptor testDescriptor, String reason) { } /** * Must be called when the execution of a leaf or subtree of the test tree * is about to be started. * *

The {@link TestDescriptor} may represent a test or a container. In the * case of a container, engines have to fire additional events for its * children. * *

This method may only be called if the test or container has not * been {@linkplain #executionSkipped skipped}. * *

This method must be called for a container {@code TestDescriptor} * before {@linkplain #executionStarted starting} or * {@linkplain #executionSkipped skipping} any of its children. * * @param testDescriptor the descriptor of the started test or container */ default void executionStarted(TestDescriptor testDescriptor) { } /** * Must be called when the execution of a leaf or subtree of the test tree * has finished, regardless of the outcome. * *

The {@link TestDescriptor} may represent a test or a container. * *

This method may only be called if the test or container has not * been {@linkplain #executionSkipped skipped}. * *

This method must be called for a container {@code TestIdentifier} * after all of its children have been * {@linkplain #executionSkipped skipped} or have * {@linkplain #executionFinished finished}. * *

The {@link TestExecutionResult} describes the result of the execution * for the supplied {@code testDescriptor}. The result does not include or * aggregate the results of its children. For example, a container with a * failing test must be reported as {@link Status#SUCCESSFUL SUCCESSFUL} even * if one or more of its children are reported as {@link Status#FAILED FAILED}. * * @param testDescriptor the descriptor of the finished test or container * @param testExecutionResult the (unaggregated) result of the execution for * the supplied {@code TestDescriptor} * * @see TestExecutionResult */ default void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { } /** * Can be called for any {@link TestDescriptor} in order to publish additional * information to the reporting infrastructure — for example: * *

    *
  • Output that would otherwise go to {@code System.out}
  • *
  • Information about test context or test data
  • *
* *

The current lifecycle state of the supplied {@code TestDescriptor} is * not relevant: reporting events can occur at any time. * * @param testDescriptor the descriptor of the test or container to which * the reporting entry belongs * @param entry a {@code ReportEntry} instance to be published */ default void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java000066400000000000000000000057601455764576500333010ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Provides a single {@link TestEngine} access to the information necessary to * execute its tests. * *

A request contains an engine's root {@link TestDescriptor}, the * {@link EngineExecutionListener} to be notified of test execution events, and * {@link ConfigurationParameters} that the engine may use to influence test * execution. * * @since 1.0 * @see TestEngine */ @API(status = STABLE, since = "1.0") public class ExecutionRequest { private final TestDescriptor rootTestDescriptor; private final EngineExecutionListener engineExecutionListener; private final ConfigurationParameters configurationParameters; @API(status = INTERNAL, since = "1.0") public ExecutionRequest(TestDescriptor rootTestDescriptor, EngineExecutionListener engineExecutionListener, ConfigurationParameters configurationParameters) { this.rootTestDescriptor = rootTestDescriptor; this.engineExecutionListener = engineExecutionListener; this.configurationParameters = configurationParameters; } /** * Factory for creating an execution request. * * @param rootTestDescriptor the engine's root {@link TestDescriptor} * @param engineExecutionListener the {@link EngineExecutionListener} to be * notified of test execution events * @param configurationParameters {@link ConfigurationParameters} that the * engine may use to influence test execution * @return a new {@code ExecutionRequest}; never {@code null} * @since 1.9 */ @API(status = STABLE, since = "1.9") public static ExecutionRequest create(TestDescriptor rootTestDescriptor, EngineExecutionListener engineExecutionListener, ConfigurationParameters configurationParameters) { return new ExecutionRequest(rootTestDescriptor, engineExecutionListener, configurationParameters); } /** * Get the root {@link TestDescriptor} of the engine that processes this * request. * *

Note: the root descriptor is the * {@code TestDescriptor} returned by * {@link TestEngine#discover(EngineDiscoveryRequest, UniqueId)}. */ public TestDescriptor getRootTestDescriptor() { return this.rootTestDescriptor; } /** * Get the {@link EngineExecutionListener} to be notified of test execution * events. */ public EngineExecutionListener getEngineExecutionListener() { return this.engineExecutionListener; } /** * Get the {@link ConfigurationParameters} that the engine may use to * influence test execution. */ public ConfigurationParameters getConfigurationParameters() { return this.configurationParameters; } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java000066400000000000000000000067311455764576500312110ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.CompositeFilter.alwaysIncluded; import java.util.Collection; import java.util.function.Function; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; /** * A {@link Filter} can be applied to determine if an object should be * included or excluded in a result set. * *

For example, tests may be filtered during or after test discovery * based on certain criteria. * *

Clients should not implement this interface directly but rather one of * its subinterfaces. * * @since 1.0 * @see DiscoveryFilter */ @FunctionalInterface @API(status = STABLE, since = "1.0") public interface Filter { /** * Return a filter that will include elements if and only if all of the * filters in the supplied array of {@link Filter filters} include it. * *

If the array is empty, the returned filter will include all elements * it is asked to filter. * * @param filters the array of filters to compose; never {@code null} * @see #composeFilters(Collection) */ @SafeVarargs @SuppressWarnings("varargs") static Filter composeFilters(Filter... filters) { Preconditions.notNull(filters, "filters array must not be null"); Preconditions.containsNoNullElements(filters, "individual filters must not be null"); if (filters.length == 0) { return alwaysIncluded(); } if (filters.length == 1) { return filters[0]; } return new CompositeFilter<>(asList(filters)); } /** * Return a filter that will include elements if and only if all of the * filters in the supplied collection of {@link Filter filters} include it. * *

If the collection is empty, the returned filter will include all * elements it is asked to filter. * * @param filters the collection of filters to compose; never {@code null} * @see #composeFilters(Filter...) */ static Filter composeFilters(Collection> filters) { Preconditions.notNull(filters, "Filters must not be null"); if (filters.isEmpty()) { return alwaysIncluded(); } if (filters.size() == 1) { return getOnlyElement(filters); } return new CompositeFilter<>(filters); } /** * Return a filter that will include elements if and only if the adapted * {@code Filter} includes the value converted using the supplied * {@link Function}. * * @param adaptee the filter to be adapted * @param converter the converter function to apply */ static Filter adaptFilter(Filter adaptee, Function converter) { return input -> adaptee.apply(converter.apply(input)); } /** * Apply this filter to the supplied object. */ FilterResult apply(T object); /** * Return a {@link Predicate} that returns {@code true} if this filter * includes the object supplied to the predicate's * {@link Predicate#test test} method. */ default Predicate toPredicate() { return object -> apply(object).included(); } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/FilterResult.java000066400000000000000000000061041455764576500324020ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; /** * The result of applying a {@link Filter}. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class FilterResult { /** * Factory for creating included results. * * @param reason the reason why the filtered object was included * @return an included {@code FilterResult} with the given reason */ public static FilterResult included(String reason) { return new FilterResult(true, reason); } /** * Factory for creating excluded results. * * @param reason the reason why the filtered object was excluded * @return an excluded {@code FilterResult} with the given reason */ public static FilterResult excluded(String reason) { return new FilterResult(false, reason); } /** * Factory for creating filter results based on the condition given. * * @param included whether or not the filtered object should be included * @return a valid {@code FilterResult} for the given condition */ public static FilterResult includedIf(boolean included) { return includedIf(included, () -> null, () -> null); } /** * Factory for creating filter results based on the condition given. * * @param included whether or not the filtered object should be included * @param inclusionReasonSupplier supplier for the reason in case of inclusion * @param exclusionReasonSupplier supplier for the reason in case of exclusion * @return a valid {@code FilterResult} for the given condition */ public static FilterResult includedIf(boolean included, Supplier inclusionReasonSupplier, Supplier exclusionReasonSupplier) { return included ? included(inclusionReasonSupplier.get()) : excluded(exclusionReasonSupplier.get()); } private final boolean included; private final Optional reason; private FilterResult(boolean included, String reason) { this.included = included; this.reason = Optional.ofNullable(reason); } /** * @return {@code true} if the filtered object should be included */ public boolean included() { return this.included; } /** * @return {@code true} if the filtered object should be excluded */ public boolean excluded() { return !included(); } /** * Get the reason why the filtered object should be included or excluded, * if available. */ public Optional getReason() { return this.reason; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("included", this.included) .append("reason", this.reason.orElse("")) .toString(); // @formatter:on } } SelectorResolutionResult.java000066400000000000000000000063121455764576500347430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code SelectorResolutionResult} encapsulates the result of resolving a * {@link DiscoverySelector} by a {@link TestEngine}. * *

A {@code SelectorResolutionResult} consists of a mandatory * {@link #getStatus() Status} and an optional {@link #getThrowable() Throwable}. * * @since 1.6 */ @API(status = STABLE, since = "1.10") public class SelectorResolutionResult { /** * Status of resolving a {@link DiscoverySelector}. */ public enum Status { /** * Indicates that the {@link TestEngine} has successfully resolved the * selector. */ RESOLVED, /** * Indicates that the {@link TestEngine} was unable to resolve the * selector. */ UNRESOLVED, /** * Indicates that the {@link TestEngine} has encountered an error while * resolving the selector. */ FAILED } private static final SelectorResolutionResult RESOLVED_RESULT = new SelectorResolutionResult(Status.RESOLVED, null); private static final SelectorResolutionResult UNRESOLVED_RESULT = new SelectorResolutionResult(Status.UNRESOLVED, null); /** * Create a {@code SelectorResolutionResult} for a resolved * selector. * @return the {@code SelectorResolutionResult}; never {@code null} */ public static SelectorResolutionResult resolved() { return RESOLVED_RESULT; } /** * Create a {@code SelectorResolutionResult} for an unresolved * selector. * @return the {@code SelectorResolutionResult}; never {@code null} */ public static SelectorResolutionResult unresolved() { return UNRESOLVED_RESULT; } /** * Create a {@code SelectorResolutionResult} for a failed * selector resolution. * @return the {@code SelectorResolutionResult}; never {@code null} */ public static SelectorResolutionResult failed(Throwable throwable) { return new SelectorResolutionResult(Status.FAILED, throwable); } private final Status status; private final Throwable throwable; private SelectorResolutionResult(Status status, Throwable throwable) { this.status = status; this.throwable = throwable; } /** * Get the {@linkplain Status status} of this result. * * @return the status; never {@code null} */ public Status getStatus() { return status; } /** * Get the throwable that caused this result, if available. * * @return an {@code Optional} containing the throwable; never {@code null} * but potentially empty */ public Optional getThrowable() { return Optional.ofNullable(throwable); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("status", status) .append("throwable", throwable) .toString(); // @formatter:on } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/TestDescriptor.java000066400000000000000000000222261455764576500327370ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; /** * Mutable descriptor for a test or container that has been discovered by a * {@link TestEngine}. * * @since 1.0 * @see TestEngine */ @API(status = STABLE, since = "1.0") public interface TestDescriptor { /** * Get the unique identifier (UID) for this descriptor. * *

Uniqueness must be guaranteed across an entire test plan, * regardless of how many engines are used behind the scenes. * * @return the {@code UniqueId} for this descriptor; never {@code null} */ UniqueId getUniqueId(); /** * Get the display name for this descriptor. * *

A display name is a human-readable name for a test or * container that is typically used for test reporting in IDEs and build * tools. Display names may contain spaces, special characters, and emoji, * and the format may be customized by {@link TestEngine TestEngines} or * potentially by end users as well. Consequently, display names should * never be parsed; rather, they should be used for display purposes only. * * @return the display name for this descriptor; never {@code null} or blank * @see #getSource() */ String getDisplayName(); /** * Get the name of this descriptor in a format that is suitable for legacy * reporting infrastructure — for example, for reporting systems built * on the Ant-based XML reporting format for JUnit 4. * *

The default implementation delegates to {@link #getDisplayName()}. * * @return the legacy reporting name; never {@code null} or blank */ default String getLegacyReportingName() { return getDisplayName(); } /** * Get the set of {@linkplain TestTag tags} associated with this descriptor. * * @return the set of tags associated with this descriptor; never {@code null} * but potentially empty * @see TestTag */ Set getTags(); /** * Get the {@linkplain TestSource source} of the test or container described * by this descriptor, if available. * * @see TestSource */ Optional getSource(); /** * Get the parent of this descriptor, if available. */ Optional getParent(); /** * Set the parent of this descriptor. * * @param parent the new parent of this descriptor; may be {@code null}. */ void setParent(TestDescriptor parent); /** * Get the immutable set of children of this descriptor. * * @return the set of children of this descriptor; neither {@code null} * nor mutable, but potentially empty * @see #getDescendants() */ Set getChildren(); /** * Get the immutable set of all ancestors of this descriptor. * *

An ancestor is the parent of this descriptor or the parent of * one of its parents, recursively. * * @see #getParent() */ @API(status = STABLE, since = "1.10") default Set getAncestors() { if (!getParent().isPresent()) { return Collections.emptySet(); } TestDescriptor parent = getParent().get(); Set ancestors = new LinkedHashSet<>(); ancestors.add(parent); // Need to recurse? if (parent.getParent().isPresent()) { ancestors.addAll(parent.getAncestors()); } return Collections.unmodifiableSet(ancestors); } /** * Get the immutable set of all descendants of this descriptor. * *

A descendant is a child of this descriptor or a child of one of * its children, recursively. * * @see #getChildren() */ default Set getDescendants() { Set descendants = new LinkedHashSet<>(); descendants.addAll(getChildren()); for (TestDescriptor child : getChildren()) { descendants.addAll(child.getDescendants()); } return Collections.unmodifiableSet(descendants); } /** * Add a child to this descriptor. * * @param descriptor the child to add to this descriptor; never {@code null} */ void addChild(TestDescriptor descriptor); /** * Remove a child from this descriptor. * * @param descriptor the child to remove from this descriptor; never * {@code null} */ void removeChild(TestDescriptor descriptor); /** * Remove this non-root descriptor from its parent and remove all the * children from this descriptor. * *

If this method is invoked on a {@linkplain #isRoot root} descriptor, * this method must throw a {@link org.junit.platform.commons.JUnitException * JUnitException} explaining that a root cannot be removed from the * hierarchy. */ void removeFromHierarchy(); /** * Determine if this descriptor is a root descriptor. * *

A root descriptor is a descriptor without a parent. */ default boolean isRoot() { return !getParent().isPresent(); } /** * Determine the {@link Type} of this descriptor. * * @return the descriptor type; never {@code null}. * @see #isContainer() * @see #isTest() */ Type getType(); /** * Determine if this descriptor describes a container. * *

The default implementation delegates to {@link Type#isContainer()}. */ default boolean isContainer() { return getType().isContainer(); } /** * Determine if this descriptor describes a test. * *

The default implementation delegates to {@link Type#isTest()}. */ default boolean isTest() { return getType().isTest(); } /** * Determine if this descriptor may register dynamic tests during execution. * *

The default implementation assumes tests are usually known during * discovery and thus returns {@code false}. */ default boolean mayRegisterTests() { return false; } /** * Determine if the supplied descriptor (or any of its descendants) * {@linkplain TestDescriptor#isTest() is a test} or * {@linkplain TestDescriptor#mayRegisterTests() may potentially register * tests dynamically}. * * @param testDescriptor the {@code TestDescriptor} to check for tests; never * {@code null} * @return {@code true} if the descriptor is a test, contains tests, or may * later register tests dynamically */ static boolean containsTests(TestDescriptor testDescriptor) { Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); return testDescriptor.isTest() || testDescriptor.mayRegisterTests() || testDescriptor.getChildren().stream().anyMatch(TestDescriptor::containsTests); } /** * Remove this descriptor from the hierarchy unless it is a root or contains * tests. * *

A concrete {@link TestEngine} may override this method in order to * implement a different algorithm or to skip pruning altogether. * * @see #isRoot() * @see #containsTests(TestDescriptor) * @see #removeFromHierarchy() */ default void prune() { if (!isRoot() && !containsTests(this)) { removeFromHierarchy(); } } /** * Find the descriptor with the supplied unique ID. * *

The search algorithm begins with this descriptor and then searches * through its descendants. * * @param uniqueId the {@code UniqueId} to search for; never {@code null} */ Optional findByUniqueId(UniqueId uniqueId); /** * Accept a {@link Visitor} to the subtree starting with this descriptor. * * @param visitor the {@code Visitor} to accept; never {@code null} */ default void accept(Visitor visitor) { Preconditions.notNull(visitor, "Visitor must not be null"); visitor.visit(this); // Create a copy of the set in order to avoid a ConcurrentModificationException new LinkedHashSet<>(this.getChildren()).forEach(child -> child.accept(visitor)); } /** * Visitor for the tree-like {@link TestDescriptor} structure. * * @see TestDescriptor#accept(Visitor) */ @FunctionalInterface interface Visitor { /** * Visit a {@link TestDescriptor}. * * @param descriptor the {@code TestDescriptor} to visit; never {@code null} */ void visit(TestDescriptor descriptor); } /** * Supported types for {@link TestDescriptor TestDescriptors}. */ enum Type { /** * Denotes that the {@link TestDescriptor} is for a container. */ CONTAINER, /** * Denotes that the {@link TestDescriptor} is for a test. */ TEST, /** * Denotes that the {@link TestDescriptor} is for a test * that may potentially also be a container. */ CONTAINER_AND_TEST; /** * @return {@code true} if this type represents a descriptor that can * contain other descriptors */ public boolean isContainer() { return this == CONTAINER || this == CONTAINER_AND_TEST; } /** * @return {@code true} if this type represents a descriptor for a test */ public boolean isTest() { return this == TEST || this == CONTAINER_AND_TEST; } } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/TestEngine.java000066400000000000000000000174301455764576500320270ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.ModuleUtils; import org.junit.platform.commons.util.PackageUtils; /** * A {@code TestEngine} facilitates discovery and execution of * tests for a particular programming model. * *

For example, JUnit provides a {@code TestEngine} that discovers and * executes tests written using the JUnit Jupiter programming model. * *

Every {@code TestEngine} must {@linkplain #getId provide its own unique ID}, * {@linkplain #discover discover tests} from * {@link EngineDiscoveryRequest EngineDiscoveryRequests}, * and {@linkplain #execute execute those tests} according to * {@link ExecutionRequest ExecutionRequests}. * *

In order to facilitate test discovery within IDEs and tools prior * to launching the JUnit Platform, {@code TestEngine} implementations are * encouraged to make use of the * {@link org.junit.platform.commons.annotation.Testable @Testable} annotation. * For example, the {@code @Test} and {@code @TestFactory} annotations in JUnit * Jupiter are meta-annotated with {@code @Testable}. Consult the Javadoc for * {@code @Testable} for further details. * * @since 1.0 * @see org.junit.platform.engine.EngineDiscoveryRequest * @see org.junit.platform.engine.ExecutionRequest * @see org.junit.platform.commons.annotation.Testable */ @API(status = STABLE, since = "1.0") public interface TestEngine { /** * Get the ID that uniquely identifies this test engine. * *

Each test engine must provide a unique ID. For example, JUnit Vintage * and JUnit Jupiter use {@code "junit-vintage"} and {@code "junit-jupiter"}, * respectively. When in doubt, you may use the fully qualified name of your * custom {@code TestEngine} implementation class. */ String getId(); /** * Discover tests according to the supplied {@link EngineDiscoveryRequest}. * *

The supplied {@link UniqueId} must be used as the unique ID of the * returned root {@link TestDescriptor}. In addition, the {@code UniqueId} * must be used to create unique IDs for children of the root's descriptor * by calling {@link UniqueId#append}. * * @param discoveryRequest the discovery request; never {@code null} * @param uniqueId the unique ID to be used for this test engine's * {@code TestDescriptor}; never {@code null} * @return the root {@code TestDescriptor} of this engine, typically an * instance of {@code EngineDescriptor} * @see org.junit.platform.engine.support.descriptor.EngineDescriptor */ TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId); /** * Execute tests according to the supplied {@link ExecutionRequest}. * *

The {@code request} passed to this method contains the root * {@link TestDescriptor} that was previously returned by {@link #discover}, * the {@link EngineExecutionListener} to be notified of test execution * events, and {@link ConfigurationParameters} that may influence test execution. * * @param request the request to execute tests for; never {@code null} */ void execute(ExecutionRequest request); /** * Get the Group ID of the JAR in which this test engine is packaged. * *

This information is used solely for debugging and reporting purposes. * *

The default implementation returns an empty {@link Optional}, * signaling that the group ID is unknown. * *

Concrete test engine implementations may override this method in * order to provide a known group ID. * * @return an {@code Optional} containing the group ID; never {@code null} * but potentially empty if the group ID is unknown * @see #getArtifactId() * @see #getVersion() */ default Optional getGroupId() { return Optional.empty(); } /** * Get the Artifact ID of the JAR in which this test engine is packaged. * *

This information is used solely for debugging and reporting purposes. * *

The default implementation assumes the implementation title is equivalent * to the artifact ID and therefore attempts to query the * {@linkplain Package#getImplementationTitle() implementation title} * from the package attributes for the {@link Package} in which the engine * resides. Note that a package only has attributes if the information is * defined in the {@link java.util.jar.Manifest Manifest} of the JAR * containing that package, and if the class loader created the * {@link Package} instance with the attributes from the manifest. * *

If the implementation title cannot be queried from the package * attributes, the default implementation returns an empty * {@link Optional}. * *

Concrete test engine implementations may override this method in * order to determine the artifact ID by some other means. * * @implNote Since JUnit Platform version 1.1 this default implementation * returns the "module name" stored in the module (modular jar on the * module-path) of this test engine. * * @return an {@code Optional} containing the artifact ID; never * {@code null} but potentially empty if the artifact ID is unknown * @see Class#getPackage() * @see Package#getImplementationTitle() * @see #getGroupId() * @see #getVersion() */ default Optional getArtifactId() { Optional moduleName = ModuleUtils.getModuleName(getClass()); if (moduleName.isPresent()) { return moduleName; } return PackageUtils.getAttribute(getClass(), Package::getImplementationTitle); } /** * Get the version of this test engine. * *

This information is used solely for debugging and reporting purposes. * *

Initially, the default implementation tries to retrieve the engine * version from the manifest attribute named: {@code "Engine-Version-" + getId()} * *

Then the default implementation attempts to query the * {@linkplain Package#getImplementationVersion() implementation version} * from the package attributes for the {@link Package} in which the engine * resides. Note that a package only has attributes if the information is * defined in the {@link java.util.jar.Manifest Manifest} of the JAR * containing that package, and if the class loader created the * {@link Package} instance with the attributes from the manifest. * *

If the implementation version cannot be queried from the package * attributes, the default implementation returns {@code "DEVELOPMENT"}. * *

Concrete test engine implementations may override this method to * determine the version by some other means. * *

implNote: Since JUnit Platform version 1.1 this default implementation * honors the "raw version" information stored in the module (modular jar * on the module-path) of this test engine. * * @return an {@code Optional} containing the version; never {@code null} * but potentially empty if the version is unknown * @see Class#getPackage() * @see Package#getImplementationVersion() * @see #getGroupId() * @see #getArtifactId() */ default Optional getVersion() { Optional standalone = PackageUtils.getAttribute(getClass(), "Engine-Version-" + getId()); if (standalone.isPresent()) { return standalone; } String fallback = "DEVELOPMENT"; Optional moduleVersion = ModuleUtils.getModuleVersion(getClass()); if (moduleVersion.isPresent()) { return moduleVersion; } return Optional.of(PackageUtils.getAttribute(getClass(), Package::getImplementationVersion).orElse(fallback)); } } TestExecutionResult.java000066400000000000000000000071751455764576500337120ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code TestExecutionResult} encapsulates the result of executing a single test * or container. * *

A {@code TestExecutionResult} consists of a mandatory * {@link #getStatus() Status} and an optional {@link #getThrowable() Throwable}. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class TestExecutionResult { /** * Status of executing a single test or container. */ public enum Status { /** * Indicates that the execution of a test or container was * successful. */ SUCCESSFUL, /** * Indicates that the execution of a test or container was * aborted (started but not finished). */ ABORTED, /** * Indicates that the execution of a test or container failed. */ FAILED; } private static final TestExecutionResult SUCCESSFUL_RESULT = new TestExecutionResult(SUCCESSFUL, null); /** * Create a {@code TestExecutionResult} for a successful execution * of a test or container. * @return the {@code TestExecutionResult}; never {@code null} */ public static TestExecutionResult successful() { return SUCCESSFUL_RESULT; } /** * Create a {@code TestExecutionResult} for an aborted execution * of a test or container with the supplied {@link Throwable throwable}. * * @param throwable the throwable that caused the aborted execution; may be * {@code null} * @return the {@code TestExecutionResult}; never {@code null} */ public static TestExecutionResult aborted(Throwable throwable) { return new TestExecutionResult(ABORTED, throwable); } /** * Create a {@code TestExecutionResult} for a failed execution * of a test or container with the supplied {@link Throwable throwable}. * * @param throwable the throwable that caused the failed execution; may be * {@code null} * @return the {@code TestExecutionResult}; never {@code null} */ public static TestExecutionResult failed(Throwable throwable) { return new TestExecutionResult(FAILED, throwable); } private final Status status; private final Throwable throwable; private TestExecutionResult(Status status, Throwable throwable) { this.status = Preconditions.notNull(status, "Status must not be null"); this.throwable = throwable; } /** * Get the {@linkplain Status status} of this result. * * @return the status; never {@code null} */ public Status getStatus() { return status; } /** * Get the throwable that caused this result, if available. * * @return an {@code Optional} containing the throwable; never {@code null} * but potentially empty */ public Optional getThrowable() { return Optional.ofNullable(throwable); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("status", status) .append("throwable", throwable) .toString(); // @formatter:on } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/TestSource.java000066400000000000000000000017311455764576500320570ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serializable; import org.apiguardian.api.API; /** * Representation of the source of a test or container used to navigate to * its location by IDEs and build tools. * *

This is a marker interface. Clients need to check instances for concrete * subclasses or subinterfaces. * *

Implementations of this interface need to ensure that they are * serializable and immutable since they may be used as data * transfer objects. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public interface TestSource extends Serializable { } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java000066400000000000000000000106311455764576500313310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; /** * Immutable value object for a tag that is assigned to a test or * container. * * @since 1.0 * @see #isValid(String) * @see #create(String) */ @API(status = STABLE, since = "1.0") public final class TestTag implements Serializable { private static final long serialVersionUID = 1L; private final String name; /** * Reserved characters that are not permissible as part of a tag name. * *

    *
  • {@code ,}: comma
  • *
  • {@code (}: left parenthesis
  • *
  • {@code )}: right parenthesis
  • *
  • {@code &}: ampersand
  • *
  • {@code |}: vertical bar
  • *
  • {@code !}: exclamation point
  • *
*/ public static final Set RESERVED_CHARACTERS = Collections.unmodifiableSet( new HashSet<>(Arrays.asList(",", "(", ")", "&", "|", "!"))); /** * Determine if the supplied tag name is valid with regard to the supported * syntax for tags. * *

Syntax Rules for Tags

*
    *
  • A tag must not be {@code null}.
  • *
  • A tag must not be blank.
  • *
  • A trimmed tag must not contain whitespace.
  • *
  • A trimmed tag must not contain ISO control characters.
  • *
  • A trimmed tag must not contain {@linkplain #RESERVED_CHARACTERS * reserved characters}.
  • *
* *

If this method returns {@code true} for a given name, it is then a * valid candidate for the {@link TestTag#create(String) create()} factory * method. * * @param name the name of the tag to validate; may be {@code null} or blank * @return {@code true} if the supplied tag name conforms to the supported * syntax for tags * @see StringUtils#isNotBlank(String) * @see String#trim() * @see StringUtils#doesNotContainWhitespace(String) * @see StringUtils#doesNotContainIsoControlCharacter(String) * @see #RESERVED_CHARACTERS * @see TestTag#create(String) */ public static boolean isValid(String name) { if (name == null) { return false; } name = name.trim(); return !name.isEmpty() && // StringUtils.doesNotContainWhitespace(name) && // StringUtils.doesNotContainIsoControlCharacter(name) && // doesNotContainReservedCharacter(name); } private static boolean doesNotContainReservedCharacter(String str) { return RESERVED_CHARACTERS.stream().noneMatch(str::contains); } /** * Create a {@code TestTag} from the supplied {@code name}. * *

Consider checking whether the syntax of the supplied {@code name} * is {@linkplain #isValid(String) valid} before attempting to create a * {@code TestTag} using this factory method. * *

Note: the supplied {@code name} will be {@linkplain String#trim() trimmed}. * * @param name the name of the tag; must be syntactically valid * @throws PreconditionViolationException if the supplied tag name is not * syntactically valid * @see TestTag#isValid(String) */ public static TestTag create(String name) throws PreconditionViolationException { return new TestTag(name); } private TestTag(String name) { Preconditions.condition(TestTag.isValid(name), () -> String.format("Tag name [%s] must be syntactically valid", name)); this.name = name.trim(); } /** * Get the name of this tag. * * @return the name of this tag; never {@code null} or blank */ public String getName() { return this.name; } @Override public boolean equals(Object obj) { if (obj instanceof TestTag) { TestTag that = (TestTag) obj; return Objects.equals(this.name, that.name); } return false; } @Override public int hashCode() { return this.name.hashCode(); } @Override public String toString() { return this.name; } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java000066400000000000000000000254011455764576500315020ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static java.util.Collections.singletonList; import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serializable; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code UniqueId} encapsulates the creation, parsing, and display of unique IDs * for {@link TestDescriptor TestDescriptors}. * *

Instances of this class have value semantics and are immutable. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class UniqueId implements Cloneable, Serializable { private static final long serialVersionUID = 1L; private static final String ENGINE_SEGMENT_TYPE = "engine"; /** * Parse a {@code UniqueId} from the supplied string representation using the * default format. * * @param uniqueId the string representation to parse; never {@code null} or blank * @return a properly constructed {@code UniqueId} * @throws JUnitException if the string cannot be parsed */ public static UniqueId parse(String uniqueId) throws JUnitException { Preconditions.notBlank(uniqueId, "Unique ID string must not be null or blank"); return UniqueIdFormat.getDefault().parse(uniqueId); } /** * Create an engine's unique ID from its {@code engineId} using the default * format. * *

The engine ID will be stored in a {@link Segment} with * {@link Segment#getType type} {@code "engine"}. * * @param engineId the engine ID; never {@code null} or blank * @see #root(String, String) */ public static UniqueId forEngine(String engineId) { Preconditions.notBlank(engineId, "engineId must not be null or blank"); return root(ENGINE_SEGMENT_TYPE, engineId); } /** * Create a root unique ID from the supplied {@code segmentType} and * {@code value} using the default format. * * @param segmentType the segment type; never {@code null} or blank * @param value the value; never {@code null} or blank * @see #forEngine(String) */ public static UniqueId root(String segmentType, String value) { return new UniqueId(UniqueIdFormat.getDefault(), new Segment(segmentType, value)); } private final UniqueIdFormat uniqueIdFormat; @SuppressWarnings({ "serial", "RedundantSuppression" }) // always used with serializable implementation (singletonList() or ArrayList) private final List segments; // lazily computed private transient int hashCode; // lazily computed private transient SoftReference toString; private UniqueId(UniqueIdFormat uniqueIdFormat, Segment segment) { this(uniqueIdFormat, singletonList(segment)); } /** * Initialize a {@code UniqueId} instance. * * @implNote A defensive copy of the segment list is not created by * this implementation. All callers should immediately drop the reference * to the list instance that they pass into this constructor. */ UniqueId(UniqueIdFormat uniqueIdFormat, List segments) { this.uniqueIdFormat = uniqueIdFormat; this.segments = segments; } final Optional getRoot() { return this.segments.isEmpty() ? Optional.empty() : Optional.of(this.segments.get(0)); } /** * Get the engine ID stored in this {@code UniqueId}, if available. * * @see #forEngine(String) */ public final Optional getEngineId() { return getRoot().filter(segment -> segment.getType().equals(ENGINE_SEGMENT_TYPE)).map(Segment::getValue); } /** * Get the immutable list of {@linkplain Segment segments} that make up this * {@code UniqueId}. */ public final List getSegments() { return unmodifiableList(this.segments); } /** * Construct a new {@code UniqueId} by appending a new {@link Segment}, based * on the supplied {@code segmentType} and {@code value}, to the end of this * {@code UniqueId}. * *

This {@code UniqueId} will not be modified. * *

Neither the {@code segmentType} nor the {@code value} may contain any * of the special characters used for constructing the string representation * of this {@code UniqueId}. * * @param segmentType the type of the segment; never {@code null} or blank * @param value the value of the segment; never {@code null} or blank */ public final UniqueId append(String segmentType, String value) { return append(new Segment(segmentType, value)); } /** * Construct a new {@code UniqueId} by appending a new {@link Segment} to * the end of this {@code UniqueId}. * *

This {@code UniqueId} will not be modified. * * @param segment the segment to be appended; never {@code null} * * @since 1.1 */ @API(status = STABLE, since = "1.1") public final UniqueId append(Segment segment) { Preconditions.notNull(segment, "segment must not be null"); List baseSegments = new ArrayList<>(this.segments.size() + 1); baseSegments.addAll(this.segments); baseSegments.add(segment); return new UniqueId(this.uniqueIdFormat, baseSegments); } /** * Construct a new {@code UniqueId} by appending a new {@link Segment}, based * on the supplied {@code engineId}, to the end of this {@code UniqueId}. * *

This {@code UniqueId} will not be modified. * *

The engine ID will be stored in a {@link Segment} with * {@link Segment#getType type} {@value #ENGINE_SEGMENT_TYPE}. * * @param engineId the engine ID; never {@code null} or blank * * @since 1.8 */ @API(status = STABLE, since = "1.10") public UniqueId appendEngine(String engineId) { return append(new Segment(ENGINE_SEGMENT_TYPE, engineId)); } /** * Determine if the supplied {@code UniqueId} is a prefix for this * {@code UniqueId}. * * @param potentialPrefix the {@code UniqueId} to be checked; never {@code null} * * @since 1.1 */ @API(status = STABLE, since = "1.1") public boolean hasPrefix(UniqueId potentialPrefix) { Preconditions.notNull(potentialPrefix, "potentialPrefix must not be null"); int size = this.segments.size(); int prefixSize = potentialPrefix.segments.size(); return size >= prefixSize && this.segments.subList(0, prefixSize).equals(potentialPrefix.segments); } /** * Construct a new {@code UniqueId} and removing the last {@link Segment} of * this {@code UniqueId}. * *

This {@code UniqueId} will not be modified. * * @return a new {@code UniqueId}; never {@code null} * @throws org.junit.platform.commons.PreconditionViolationException * if this {@code UniqueId} contains a single segment * @since 1.5 */ @API(status = STABLE, since = "1.5") public UniqueId removeLastSegment() { Preconditions.condition(this.segments.size() > 1, "Cannot remove last remaining segment"); return new UniqueId(uniqueIdFormat, new ArrayList<>(this.segments.subList(0, this.segments.size() - 1))); } /** * Get the last {@link Segment} of this {@code UniqueId}. * * @return the last {@code Segment}; never {@code null} * @since 1.5 */ @API(status = STABLE, since = "1.5") public Segment getLastSegment() { return this.segments.get(this.segments.size() - 1); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } UniqueId that = (UniqueId) o; return this.segments.equals(that.segments); } @Override public int hashCode() { int value = this.hashCode; if (value == 0) { value = this.segments.hashCode(); if (value == 0) { // handle the edge case of the computed hashCode being 0 value = 1; } // this is a benign race like String#hash // we potentially read and write values from multiple threads // without a happens-before relationship // however the JMM guarantees us that we only ever see values // that were valid at one point, either 0 or the hash code // so we might end up not seeing a value that a different thread // has computed or multiple threads writing the same value this.hashCode = value; } return value; } /** * Generate the unique, formatted string representation of this {@code UniqueId} * using the configured {@link UniqueIdFormat}. */ @Override public String toString() { SoftReference s = this.toString; String value = s == null ? null : s.get(); if (value == null) { value = this.uniqueIdFormat.format(this); // this is a benign race like String#hash // we potentially read and write values from multiple threads // without a happens-before relationship // however the JMM guarantees us that we only ever see values // that were valid at one point, either null or the toString value // so we might end up not seeing a value that a different thread // has computed or multiple threads writing the same value this.toString = new SoftReference<>(value); } return value; } /** * A segment of a {@link UniqueId} comprises a type and a * value. */ @API(status = STABLE, since = "1.0") public static class Segment implements Serializable { private static final long serialVersionUID = 1L; private final String type; private final String value; /** * Create a new {@code Segment} using the supplied {@code type} and * {@code value}. * * @param type the type of this segment * @param value the value of this segment */ Segment(String type, String value) { Preconditions.notBlank(type, "type must not be null or blank"); Preconditions.notBlank(value, "value must not be null or blank"); this.type = type; this.value = value; } /** * Get the type of this segment. */ public String getType() { return this.type; } /** * Get the value of this segment. */ public String getValue() { return this.value; } @Override public int hashCode() { return Objects.hash(this.type, this.value); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Segment that = (Segment) o; return Objects.equals(this.type, that.type) && Objects.equals(this.value, that.value); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("type", this.type) .append("value", this.value) .toString(); // @formatter:on } } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java000066400000000000000000000126301455764576500326530ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.UniqueId.Segment; /** * Used to {@link #parse} a {@link UniqueId} from a string representation * or to {@link #format} a {@link UniqueId} into a string representation. * * @since 1.0 */ class UniqueIdFormat implements Serializable { private static final long serialVersionUID = 1L; private static final UniqueIdFormat defaultFormat = new UniqueIdFormat('[', ':', ']', '/'); static UniqueIdFormat getDefault() { return defaultFormat; } private static String quote(char c) { return Pattern.quote(String.valueOf(c)); } private static String encode(char c) { try { return URLEncoder.encode(String.valueOf(c), StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { throw new AssertionError("UTF-8 should be supported", e); } } private final char openSegment; private final char closeSegment; private final char segmentDelimiter; private final char typeValueSeparator; private final Pattern segmentPattern; private final HashMap encodedCharacterMap = new HashMap<>(); UniqueIdFormat(char openSegment, char typeValueSeparator, char closeSegment, char segmentDelimiter) { this.openSegment = openSegment; this.typeValueSeparator = typeValueSeparator; this.closeSegment = closeSegment; this.segmentDelimiter = segmentDelimiter; this.segmentPattern = Pattern.compile( String.format("%s(.+)%s(.+)%s", quote(openSegment), quote(typeValueSeparator), quote(closeSegment)), Pattern.DOTALL); // Compute "forbidden" character encoding map. // Note that the map is always empty at this point. Thus the use of // computeIfAbsent() is purely syntactic sugar. encodedCharacterMap.computeIfAbsent('%', UniqueIdFormat::encode); encodedCharacterMap.computeIfAbsent('+', UniqueIdFormat::encode); encodedCharacterMap.computeIfAbsent(openSegment, UniqueIdFormat::encode); encodedCharacterMap.computeIfAbsent(typeValueSeparator, UniqueIdFormat::encode); encodedCharacterMap.computeIfAbsent(closeSegment, UniqueIdFormat::encode); encodedCharacterMap.computeIfAbsent(segmentDelimiter, UniqueIdFormat::encode); } /** * Parse a {@code UniqueId} from the supplied string representation. * * @return a properly constructed {@code UniqueId} * @throws JUnitException if the string cannot be parsed */ UniqueId parse(String source) throws JUnitException { String[] parts = source.split(String.valueOf(this.segmentDelimiter)); List segments = Arrays.stream(parts).map(this::createSegment).collect(toList()); return new UniqueId(this, segments); } private Segment createSegment(String segmentString) throws JUnitException { Matcher segmentMatcher = this.segmentPattern.matcher(segmentString); if (!segmentMatcher.matches()) { throw new JUnitException(String.format("'%s' is not a well-formed UniqueId segment", segmentString)); } String type = decode(checkAllowed(segmentMatcher.group(1))); String value = decode(checkAllowed(segmentMatcher.group(2))); return new Segment(type, value); } private String checkAllowed(String typeOrValue) { checkDoesNotContain(typeOrValue, this.segmentDelimiter); checkDoesNotContain(typeOrValue, this.typeValueSeparator); checkDoesNotContain(typeOrValue, this.openSegment); checkDoesNotContain(typeOrValue, this.closeSegment); return typeOrValue; } private void checkDoesNotContain(String typeOrValue, char forbiddenCharacter) { Preconditions.condition(typeOrValue.indexOf(forbiddenCharacter) < 0, () -> String.format("type or value '%s' must not contain '%s'", typeOrValue, forbiddenCharacter)); } /** * Format and return the string representation of the supplied {@code UniqueId}. */ String format(UniqueId uniqueId) { // @formatter:off return uniqueId.getSegments().stream() .map(this::describe) .collect(joining(String.valueOf(this.segmentDelimiter))); // @formatter:on } private String describe(Segment segment) { String body = encode(segment.getType()) + typeValueSeparator + encode(segment.getValue()); return openSegment + body + closeSegment; } private String encode(String s) { StringBuilder builder = new StringBuilder(s.length()); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); String value = encodedCharacterMap.get(c); if (value == null) { builder.append(c); continue; } builder.append(value); } return builder.toString(); } private static String decode(String s) { try { return URLDecoder.decode(s, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { throw new JUnitException("UTF-8 should be supported", e); } } } junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/000077500000000000000000000000001455764576500311215ustar00rootroot00000000000000AbstractClassNameFilter.java000066400000000000000000000031531455764576500364070ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import org.junit.platform.commons.util.Preconditions; /** * Abstract {@link ClassNameFilter} that servers as a superclass * for filters including or excluding fully qualified class names * based on pattern-matching. * * @since 1.0 */ abstract class AbstractClassNameFilter implements ClassNameFilter { protected final List patterns; protected final String patternDescription; AbstractClassNameFilter(String... patterns) { Preconditions.notEmpty(patterns, "patterns array must not be null or empty"); Preconditions.containsNoNullElements(patterns, "patterns array must not contain null elements"); this.patterns = Arrays.stream(patterns).map(Pattern::compile).collect(toList()); this.patternDescription = Arrays.stream(patterns).collect(joining("' OR '", "'", "'")); } @Override public abstract Predicate toPredicate(); protected Optional findMatchingPattern(String className) { return this.patterns.stream().filter(pattern -> pattern.matcher(className).matches()).findAny(); } } ClassNameFilter.java000066400000000000000000000053561455764576500347320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.DiscoveryFilter; /** * {@link DiscoveryFilter} that is applied to the name of a {@link Class}. * * @since 1.0 * @see #includeClassNamePatterns(String...) * @see #excludeClassNamePatterns(String...) * @see PackageNameFilter */ @API(status = STABLE, since = "1.0") public interface ClassNameFilter extends DiscoveryFilter { /** * Standard include pattern in the form of a regular expression that is * used to match against fully qualified class names: * {@value org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN} * *

This pattern matches against class names beginning with {@code Test} * or ending with {@code Test} or {@code Tests} (in any package). */ // Implementation notes: // - Test.* :: "Test" prefix for classes in default package // - .+[.$]Test.* :: "Test" prefix for top-level and nested classes in a named package // - .*Tests? :: "Test" and "Tests" suffixes in any package String STANDARD_INCLUDE_PATTERN = "^(Test.*|.+[.$]Test.*|.*Tests?)$"; /** * Create a new include {@link ClassNameFilter} based on the * supplied patterns. * *

The patterns are combined using OR semantics, i.e. if the fully * qualified name of a class matches against at least one of the patterns, * the class will be included in the result set. * * @param patterns regular expressions to match against fully qualified * class names; never {@code null}, empty, or containing {@code null} * @see Class#getName() * @see #excludeClassNamePatterns(String...) */ static ClassNameFilter includeClassNamePatterns(String... patterns) { return new IncludeClassNameFilter(patterns); } /** * Create a new exclude {@link ClassNameFilter} based on the * supplied patterns. * *

The patterns are combined using OR semantics, i.e. if the fully * qualified name of a class matches against at least one of the patterns, * the class will be excluded from the result set. * * @param patterns regular expressions to match against fully qualified * class names; never {@code null}, empty, or containing {@code null} * @see Class#getName() * @see #includeClassNamePatterns(String...) */ static ClassNameFilter excludeClassNamePatterns(String... patterns) { return new ExcludeClassNameFilter(patterns); } } ClassSelector.java000066400000000000000000000075761455764576500344720ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a {@link Class} or class name so * that {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on classes. * *

If a Java {@link Class} reference is provided, the selector will return * that {@code Class} and its class name accordingly. If a class name is * provided, the selector will only attempt to lazily load the {@link Class} * if {@link #getJavaClass()} is invoked. * *

In this context, Java {@link Class} means anything that can be referenced * as a {@link Class} on the JVM — for example, classes from other JVM * languages such Groovy, Scala, etc. * * @since 1.0 * @see DiscoverySelectors#selectClass(String) * @see DiscoverySelectors#selectClass(Class) * @see org.junit.platform.engine.support.descriptor.ClassSource */ @API(status = STABLE, since = "1.0") public class ClassSelector implements DiscoverySelector { private final ClassLoader classLoader; private final String className; private Class javaClass; ClassSelector(ClassLoader classLoader, String className) { this.className = className; this.classLoader = classLoader; } ClassSelector(Class javaClass) { this.className = javaClass.getName(); this.classLoader = javaClass.getClassLoader(); this.javaClass = javaClass; } /** * Get the {@link ClassLoader} used to load the selected class. * * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.classLoader; } /** * Get the selected class name. */ public String getClassName() { return this.className; } /** * Get the selected {@link Class}. * *

If the {@link Class} was not provided, but only the name, this method * attempts to lazily load the {@link Class} based on its name and throws a * {@link PreconditionViolationException} if the class cannot be loaded. */ public Class getJavaClass() { if (this.javaClass == null) { // @formatter:off Try> tryToLoadClass = this.classLoader == null ? ReflectionUtils.tryToLoadClass(this.className) : ReflectionUtils.tryToLoadClass(this.className, this.classLoader); this.javaClass = tryToLoadClass.getOrThrow(cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } return this.javaClass; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ClassSelector that = (ClassSelector) o; return Objects.equals(this.className, that.className); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.className.hashCode(); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("className", this.className) .append("classLoader", this.classLoader) .toString(); // @formatter:on } } ClasspathResourceSelector.java000066400000000000000000000062711455764576500370460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects the name of a classpath resource * so that {@link org.junit.platform.engine.TestEngine TestEngines} can load resources * from the classpath — for example, to load XML or JSON files from the classpath, * potentially within JARs. * *

Since {@linkplain org.junit.platform.engine.TestEngine engines} are not * expected to modify the classpath, the classpath resource represented by this * selector must be on the classpath of the * {@linkplain Thread#getContextClassLoader() context class loader} of the * {@linkplain Thread thread} that uses it. * * @since 1.0 * @see DiscoverySelectors#selectClasspathResource(String) * @see ClasspathRootSelector * @see #getClasspathResourceName() */ @API(status = STABLE, since = "1.0") public class ClasspathResourceSelector implements DiscoverySelector { private final String classpathResourceName; private final FilePosition position; ClasspathResourceSelector(String classpathResourceName, FilePosition position) { boolean startsWithSlash = classpathResourceName.startsWith("/"); this.classpathResourceName = (startsWithSlash ? classpathResourceName.substring(1) : classpathResourceName); this.position = position; } /** * Get the name of the selected classpath resource. * *

The name of a classpath resource must follow the semantics * for resource paths as defined in {@link ClassLoader#getResource(String)}. * * @see ClassLoader#getResource(String) * @see ClassLoader#getResourceAsStream(String) * @see ClassLoader#getResources(String) */ public String getClasspathResourceName() { return this.classpathResourceName; } /** * Get the selected {@code FilePosition} within the classpath resource. */ public Optional getPosition() { return Optional.ofNullable(this.position); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ClasspathResourceSelector that = (ClasspathResourceSelector) o; return Objects.equals(this.classpathResourceName, that.classpathResourceName) && Objects.equals(this.position, that.position); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return Objects.hash(this.classpathResourceName, this.position); } @Override public String toString() { return new ToStringBuilder(this).append("classpathResourceName", this.classpathResourceName).append("position", this.position).toString(); } } ClasspathRootSelector.java000066400000000000000000000044531455764576500362020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.net.URI; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a classpath root so that * {@link org.junit.platform.engine.TestEngine TestEngines} can search for class * files or resources within the physical classpath — for example, to * scan for test classes. * *

Since {@linkplain org.junit.platform.engine.TestEngine engines} are not * expected to modify the classpath, the classpath root represented by this * selector must be on the classpath of the * {@linkplain Thread#getContextClassLoader() context class loader} of the * {@linkplain Thread thread} that uses this selector. * * @since 1.0 * @see DiscoverySelectors#selectClasspathRoots(java.util.Set) * @see ClasspathResourceSelector * @see Thread#getContextClassLoader() */ @API(status = STABLE, since = "1.0") public class ClasspathRootSelector implements DiscoverySelector { private final URI classpathRoot; ClasspathRootSelector(URI classpathRoot) { this.classpathRoot = classpathRoot; } /** * Get the selected classpath root directory as an {@link URI}. */ public URI getClasspathRoot() { return this.classpathRoot; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ClasspathRootSelector that = (ClasspathRootSelector) o; return Objects.equals(this.classpathRoot, that.classpathRoot); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.classpathRoot.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("classpathRoot", this.classpathRoot).toString(); } } DirectorySelector.java000066400000000000000000000047151455764576500353610ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a directory so that * {@link org.junit.platform.engine.TestEngine TestEngines} * can discover tests or containers based on directories in the * file system. * * @since 1.0 * @see DiscoverySelectors#selectDirectory(String) * @see DiscoverySelectors#selectDirectory(File) * @see FileSelector * @see #getDirectory() * @see #getPath() * @see #getRawPath() */ @API(status = STABLE, since = "1.0") public class DirectorySelector implements DiscoverySelector { private final String path; DirectorySelector(String path) { this.path = path; } /** * Get the selected directory as a {@link java.io.File}. * * @see #getPath() * @see #getRawPath() */ public File getDirectory() { return new File(this.path); } /** * Get the selected directory as a {@link java.nio.file.Path} using the * {@linkplain FileSystems#getDefault default} {@link FileSystem}. * * @see #getDirectory() * @see #getRawPath() */ public Path getPath() { return Paths.get(this.path); } /** * Get the selected directory as a raw path. * * @see #getDirectory() * @see #getPath() */ public String getRawPath() { return this.path; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DirectorySelector that = (DirectorySelector) o; return Objects.equals(this.path, that.path); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.path.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("path", this.path).toString(); } } DiscoverySelectors.java000066400000000000000000001173271455764576500355530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.UniqueId; /** * Collection of {@code static} factory methods for creating * {@link DiscoverySelector DiscoverySelectors}. * * @since 1.0 * @see UriSelector * @see FileSelector * @see DirectorySelector * @see ClasspathRootSelector * @see ClasspathResourceSelector * @see ModuleSelector * @see PackageSelector * @see ClassSelector * @see MethodSelector * @see NestedClassSelector * @see NestedMethodSelector * @see UniqueIdSelector */ @API(status = STABLE, since = "1.0") public final class DiscoverySelectors { private DiscoverySelectors() { /* no-op */ } /** * Create a {@code UriSelector} for the supplied URI. * * @param uri the URI to select; never {@code null} or blank * @see UriSelector * @see #selectUri(URI) * @see #selectFile(String) * @see #selectFile(File) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static UriSelector selectUri(String uri) { Preconditions.notBlank(uri, "URI must not be null or blank"); try { return new UriSelector(new URI(uri)); } catch (URISyntaxException ex) { throw new PreconditionViolationException("Failed to create a java.net.URI from: " + uri, ex); } } /** * Create a {@code UriSelector} for the supplied {@link URI}. * * @param uri the URI to select; never {@code null} * @see UriSelector * @see #selectUri(String) * @see #selectFile(String) * @see #selectFile(File) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static UriSelector selectUri(URI uri) { Preconditions.notNull(uri, "URI must not be null"); return new UriSelector(uri); } /** * Create a {@code FileSelector} for the supplied file path. * *

This method selects the file using the supplied path as is, * without verifying if the file exists. * * @param path the path to the file to select; never {@code null} or blank * @see FileSelector * @see #selectFile(File) * @see #selectFile(String, FilePosition) * @see #selectFile(File, FilePosition) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static FileSelector selectFile(String path) { return selectFile(path, null); } /** * Create a {@code FileSelector} for the supplied {@linkplain File file}. * *

This method selects the file in its {@linkplain File#getCanonicalPath() * canonical} form and throws a {@link PreconditionViolationException} if the * file does not exist. * * @param file the file to select; never {@code null} * @see FileSelector * @see #selectFile(String) * @see #selectFile(File, FilePosition) * @see #selectFile(String, FilePosition) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static FileSelector selectFile(File file) { return selectFile(file, null); } /** * Create a {@code FileSelector} for the supplied file path. * *

This method selects the file using the supplied path as is, * without verifying if the file exists. * * @param path the path to the file to select; never {@code null} or blank * @param position the position inside the file; may be {@code null} * @see FileSelector * @see #selectFile(String) * @see #selectFile(File) * @see #selectFile(File, FilePosition) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static FileSelector selectFile(String path, FilePosition position) { Preconditions.notBlank(path, "File path must not be null or blank"); return new FileSelector(path, position); } /** * Create a {@code FileSelector} for the supplied {@linkplain File file}. * *

This method selects the file in its {@linkplain File#getCanonicalPath() * canonical} form and throws a {@link PreconditionViolationException} if the * file does not exist. * * @param file the file to select; never {@code null} * @param position the position inside the file; may be {@code null} * @see FileSelector * @see #selectFile(File) * @see #selectFile(String) * @see #selectFile(String, FilePosition) * @see #selectDirectory(String) * @see #selectDirectory(File) */ public static FileSelector selectFile(File file, FilePosition position) { Preconditions.notNull(file, "File must not be null"); Preconditions.condition(file.isFile(), () -> String.format("The supplied java.io.File [%s] must represent an existing file", file)); try { return new FileSelector(file.getCanonicalPath(), position); } catch (IOException ex) { throw new PreconditionViolationException("Failed to retrieve canonical path for file: " + file, ex); } } /** * Create a {@code DirectorySelector} for the supplied directory path. * *

This method selects the directory using the supplied path as is, * without verifying if the directory exists. * * @param path the path to the directory to select; never {@code null} or blank * @see DirectorySelector * @see #selectDirectory(File) * @see #selectFile(String) * @see #selectFile(File) */ public static DirectorySelector selectDirectory(String path) { Preconditions.notBlank(path, "Directory path must not be null or blank"); return new DirectorySelector(path); } /** * Create a {@code DirectorySelector} for the supplied {@linkplain File directory}. * *

This method selects the directory in its {@linkplain File#getCanonicalPath() * canonical} form and throws a {@link PreconditionViolationException} if the * directory does not exist. * * @param directory the directory to select; never {@code null} * @see DirectorySelector * @see #selectDirectory(String) * @see #selectFile(String) * @see #selectFile(File) */ public static DirectorySelector selectDirectory(File directory) { Preconditions.notNull(directory, "Directory must not be null"); Preconditions.condition(directory.isDirectory(), () -> String.format("The supplied java.io.File [%s] must represent an existing directory", directory)); try { return new DirectorySelector(directory.getCanonicalPath()); } catch (IOException ex) { throw new PreconditionViolationException("Failed to retrieve canonical path for directory: " + directory, ex); } } /** * Create a list of {@code ClasspathRootSelectors} for the supplied * classpath roots (directories or JAR files). * *

Since the supplied paths are converted to {@link URI URIs}, the * {@link java.nio.file.FileSystem} that created them must be the * {@linkplain java.nio.file.FileSystems#getDefault() default} or one that * has been created by an installed * {@link java.nio.file.spi.FileSystemProvider}. * *

Since {@linkplain org.junit.platform.engine.TestEngine engines} are not * expected to modify the classpath, the classpath roots represented by the * resulting selectors must be on the classpath of the * {@linkplain Thread#getContextClassLoader() context class loader} of the * {@linkplain Thread thread} that uses these selectors. * * @param classpathRoots set of directories and JAR files in the filesystem * that represent classpath roots; never {@code null} * @return a list of selectors for the supplied classpath roots; elements * which do not physically exist in the filesystem will be filtered out * @see ClasspathRootSelector * @see Thread#getContextClassLoader() */ public static List selectClasspathRoots(Set classpathRoots) { Preconditions.notNull(classpathRoots, "classpathRoots must not be null"); // @formatter:off return classpathRoots.stream() .filter(Files::exists) .map(Path::toUri) .map(ClasspathRootSelector::new) // unmodifiable since selectClasspathRoots is a public, non-internal method .collect(toUnmodifiableList()); // @formatter:on } /** * Create a {@code ClasspathResourceSelector} for the supplied classpath * resource name. * *

The name of a classpath resource must follow the semantics * for resource paths as defined in {@link ClassLoader#getResource(String)}. * *

If the supplied classpath resource name is prefixed with a slash * ({@code /}), the slash will be removed. * *

Since {@linkplain org.junit.platform.engine.TestEngine engines} are not * expected to modify the classpath, the supplied classpath resource must be * on the classpath of the * {@linkplain Thread#getContextClassLoader() context class loader} of the * {@linkplain Thread thread} that uses the resulting selector. * * @param classpathResourceName the name of the classpath resource; never * {@code null} or blank * @see #selectClasspathResource(String, FilePosition) * @see ClasspathResourceSelector * @see ClassLoader#getResource(String) * @see ClassLoader#getResourceAsStream(String) * @see ClassLoader#getResources(String) */ public static ClasspathResourceSelector selectClasspathResource(String classpathResourceName) { return selectClasspathResource(classpathResourceName, null); } /** * Create a {@code ClasspathResourceSelector} for the supplied classpath * resource name. * *

The name of a classpath resource must follow the semantics * for resource paths as defined in {@link ClassLoader#getResource(String)}. * *

If the supplied classpath resource name is prefixed with a slash * ({@code /}), the slash will be removed. * *

Since {@linkplain org.junit.platform.engine.TestEngine engines} are not * expected to modify the classpath, the supplied classpath resource must be * on the classpath of the * {@linkplain Thread#getContextClassLoader() context class loader} of the * {@linkplain Thread thread} that uses the resulting selector. * * @param classpathResourceName the name of the classpath resource; never * {@code null} or blank * @param position the position inside the classpath resource; may be {@code null} * @see #selectClasspathResource(String) * @see ClasspathResourceSelector * @see ClassLoader#getResource(String) * @see ClassLoader#getResourceAsStream(String) * @see ClassLoader#getResources(String) */ public static ClasspathResourceSelector selectClasspathResource(String classpathResourceName, FilePosition position) { Preconditions.notBlank(classpathResourceName, "Classpath resource name must not be null or blank"); return new ClasspathResourceSelector(classpathResourceName, position); } /** * Create a {@code ModuleSelector} for the supplied module name. * *

The unnamed module is not supported. * * @param moduleName the module name to select; never {@code null} or blank * @since 1.1 * @see ModuleSelector */ @API(status = STABLE, since = "1.10") public static ModuleSelector selectModule(String moduleName) { Preconditions.notBlank(moduleName, "Module name must not be null or blank"); return new ModuleSelector(moduleName.trim()); } /** * Create a list of {@code ModuleSelectors} for the supplied module names. * *

The unnamed module is not supported. * * @param moduleNames the module names to select; never {@code null}, never * containing {@code null} or blank * @since 1.1 * @see ModuleSelector */ @API(status = STABLE, since = "1.10") public static List selectModules(Set moduleNames) { Preconditions.notNull(moduleNames, "Module names must not be null"); Preconditions.containsNoNullElements(moduleNames, "Individual module name must not be null"); // @formatter:off return moduleNames.stream() .map(DiscoverySelectors::selectModule) // unmodifiable since this is a public, non-internal method .collect(toUnmodifiableList()); // @formatter:on } /** * Create a {@code PackageSelector} for the supplied package name. * *

The default package is represented by an empty string ({@code ""}). * * @param packageName the package name to select; never {@code null} and * never containing whitespace only * @see PackageSelector */ public static PackageSelector selectPackage(String packageName) { Preconditions.notNull(packageName, "Package name must not be null"); Preconditions.condition(packageName.isEmpty() || !packageName.trim().isEmpty(), "Package name must not contain only whitespace"); return new PackageSelector(packageName.trim()); } /** * Create a {@code ClassSelector} for the supplied {@link Class}. * * @param clazz the class to select; never {@code null} * @see ClassSelector */ public static ClassSelector selectClass(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return new ClassSelector(clazz); } /** * Create a {@code ClassSelector} for the supplied class name. * * @param className the fully qualified name of the class to select; never * {@code null} or blank * @see ClassSelector */ public static ClassSelector selectClass(String className) { return selectClass((ClassLoader) null, className); } /** * Create a {@code ClassSelector} for the supplied class name and class loader. * * @param classLoader the class loader to use to load the class, or {@code null} * to signal that the default {@code ClassLoader} should be used * @param className the fully qualified name of the class to select; never * {@code null} or blank * @since 1.10 * @see ClassSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static ClassSelector selectClass(ClassLoader classLoader, String className) { Preconditions.notBlank(className, "Class name must not be null or blank"); return new ClassSelector(classLoader, className); } /** * Create a {@code MethodSelector} for the supplied fully qualified * method name. * *

The following formats are supported. * *

    *
  • {@code [fully qualified class name]#[methodName]}
  • *
  • {@code [fully qualified class name]#[methodName](parameter type list)} *
* *

The parameter type list is a comma-separated list of primitive * names or fully qualified class names for the types of parameters accepted * by the method. * *

Array parameter types may be specified using either the JVM's internal * String representation (e.g., {@code [[I} for {@code int[][]}, * {@code [Ljava.lang.String;} for {@code java.lang.String[]}, etc.) or * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, * etc.). * * * * * * * * * * * * * * * * *
Examples
MethodFully Qualified Method Name
{@code java.lang.String.chars()}{@code java.lang.String#chars}
{@code java.lang.String.chars()}{@code java.lang.String#chars()}
{@code java.lang.String.equalsIgnoreCase(String)}{@code java.lang.String#equalsIgnoreCase(java.lang.String)}
{@code java.lang.String.substring(int, int)}{@code java.lang.String#substring(int, int)}
{@code example.Calc.avg(int[])}{@code example.Calc#avg([I)}
{@code example.Calc.avg(int[])}{@code example.Calc#avg(int[])}
{@code example.Matrix.multiply(double[][])}{@code example.Matrix#multiply([[D)}
{@code example.Matrix.multiply(double[][])}{@code example.Matrix#multiply(double[][])}
{@code example.Service.process(String[])}{@code example.Service#process([Ljava.lang.String;)}
{@code example.Service.process(String[])}{@code example.Service#process(java.lang.String[])}
{@code example.Service.process(String[][])}{@code example.Service#process([[Ljava.lang.String;)}
{@code example.Service.process(String[][])}{@code example.Service#process(java.lang.String[][])}
* * @param fullyQualifiedMethodName the fully qualified name of the method to * select; never {@code null} or blank * @see MethodSelector */ public static MethodSelector selectMethod(String fullyQualifiedMethodName) throws PreconditionViolationException { return selectMethod((ClassLoader) null, fullyQualifiedMethodName); } /** * Create a {@code MethodSelector} for the supplied fully qualified * method name and class loader. * *

See {@link #selectMethod(String)} for the supported formats for a * fully qualified method name. * * @param classLoader the class loader to use to load the method's declaring * class, or {@code null} to signal that the default {@code ClassLoader} * should be used * @param fullyQualifiedMethodName the fully qualified name of the method to * select; never {@code null} or blank * @since 1.10 * @see #selectMethod(String) * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static MethodSelector selectMethod(ClassLoader classLoader, String fullyQualifiedMethodName) throws PreconditionViolationException { String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); return selectMethod(classLoader, methodParts[0], methodParts[1], methodParts[2]); } /** * Create a {@code MethodSelector} for the supplied class name and method name * using the default class loader. * * @param className the fully qualified name of the class in which the method * is declared, or a subclass thereof; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @see MethodSelector */ public static MethodSelector selectMethod(String className, String methodName) { return selectMethod((ClassLoader) null, className, methodName); } /** * Create a {@code MethodSelector} for the supplied class name, method name, * and class loader. * * @param classLoader the class loader to use to load the class, or {@code null} * to signal that the default {@code ClassLoader} should be used * @param className the fully qualified name of the class in which the method * is declared, or a subclass thereof; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @since 1.10 * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName) { return selectMethod(classLoader, className, methodName, ""); } /** * Create a {@code MethodSelector} for the supplied class name, method name, * and parameter type names. * *

The parameter type names {@code String} is typically a comma-separated * list of atomic types, fully qualified class names, or array types; however, * the exact syntax depends on the underlying test engine. * * @param className the fully qualified name of the class in which the method * is declared, or a subclass thereof; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * parameters * @see MethodSelector */ public static MethodSelector selectMethod(String className, String methodName, String parameterTypeNames) { return selectMethod((ClassLoader) null, className, methodName, parameterTypeNames); } /** * Create a {@code MethodSelector} for the supplied class name, method name, * parameter type names, and class loader. * *

The parameter type names {@code String} is typically a comma-separated * list of atomic types, fully qualified class names, or array types; however, * the exact syntax depends on the underlying test engine. * * @param classLoader the class loader to use to load the class, or {@code null} * to signal that the default {@code ClassLoader} should be used * @param className the fully qualified name of the class in which the method * is declared, or a subclass thereof; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * any parameters * @since 1.10 * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypeNames, "Parameter type names must not be null"); return new MethodSelector(classLoader, className, methodName, parameterTypeNames.trim()); } /** * Create a {@code MethodSelector} for the supplied {@link Class} and method name. * * @param javaClass the class in which the method is declared, or a subclass thereof; * never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @see MethodSelector */ public static MethodSelector selectMethod(Class javaClass, String methodName) { return selectMethod(javaClass, methodName, ""); } /** * Create a {@code MethodSelector} for the supplied {@link Class}, method name, * and parameter type names. * *

The parameter type names {@code String} is typically a comma-separated * list of atomic types, fully qualified class names, or array types; however, * the exact syntax depends on the underlying test engine. * * @param javaClass the class in which the method is declared, or a subclass thereof; * never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * any parameters * @see MethodSelector */ public static MethodSelector selectMethod(Class javaClass, String methodName, String parameterTypeNames) { Preconditions.notNull(javaClass, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypeNames, "Parameter type names must not be null"); return new MethodSelector(javaClass, methodName, parameterTypeNames.trim()); } /** * Create a {@code MethodSelector} for the supplied class name, method name, * and parameter types. * * @param className the fully qualified name of the class in which the method * is declared, or a subclass thereof; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypes the formal parameter types of the method; never * {@code null} though potentially empty if the method does not declare parameters * @since 1.10 * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static MethodSelector selectMethod(String className, String methodName, Class... parameterTypes) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypes, "Parameter types array must not be null"); Preconditions.containsNoNullElements(parameterTypes, "Parameter types array must not contain null elements"); return new MethodSelector((ClassLoader) null, className, methodName, parameterTypes); } /** * Create a {@code MethodSelector} for the supplied {@link Class}, method name, * and parameter types. * * @param javaClass the class in which the method is declared, or a subclass thereof; * never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypes the formal parameter types of the method; never * {@code null} though potentially empty if the method does not declare parameters * @since 1.10 * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static MethodSelector selectMethod(Class javaClass, String methodName, Class... parameterTypes) { Preconditions.notNull(javaClass, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypes, "Parameter types array must not be null"); Preconditions.containsNoNullElements(parameterTypes, "Parameter types array must not contain null elements"); return new MethodSelector(javaClass, methodName, parameterTypes); } /** * Create a {@code MethodSelector} for the supplied {@link Class} and {@link Method}. * * @param javaClass the class in which the method is declared, or a subclass thereof; * never {@code null} * @param method the method to select; never {@code null} * @see MethodSelector */ public static MethodSelector selectMethod(Class javaClass, Method method) { Preconditions.notNull(javaClass, "Class must not be null"); Preconditions.notNull(method, "Method must not be null"); return new MethodSelector(javaClass, method); } /** * Create a {@code NestedClassSelector} for the supplied nested {@link Class} and its * enclosing classes. * * @param enclosingClasses the path to the nested class to select; never {@code null} or empty * @param nestedClass the nested class to select; never {@code null} * @since 1.6 * @see NestedClassSelector */ @API(status = STABLE, since = "1.6") public static NestedClassSelector selectNestedClass(List> enclosingClasses, Class nestedClass) { Preconditions.notEmpty(enclosingClasses, "Enclosing classes must not be null or empty"); Preconditions.notNull(nestedClass, "Nested class must not be null"); return new NestedClassSelector(enclosingClasses, nestedClass); } /** * Create a {@code NestedClassSelector} for the supplied class name and its enclosing * classes' names. * * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @since 1.6 * @see NestedClassSelector */ @API(status = STABLE, since = "1.6") public static NestedClassSelector selectNestedClass(List enclosingClassNames, String nestedClassName) { return selectNestedClass((ClassLoader) null, enclosingClassNames, nestedClassName); } /** * Create a {@code NestedClassSelector} for the supplied class name, its enclosing * classes' names, and class loader. * * @param classLoader the class loader to use to load the enclosing and nested classes, or * {@code null} to signal that the default {@code ClassLoader} should be used * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @since 1.10 * @see NestedClassSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static NestedClassSelector selectNestedClass(ClassLoader classLoader, List enclosingClassNames, String nestedClassName) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); return new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); } /** * Create a {@code NestedMethodSelector} for the supplied nested class name and method name. * * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @since 1.6 * @see NestedMethodSelector */ @API(status = STABLE, since = "1.6") public static NestedMethodSelector selectNestedMethod(List enclosingClassNames, String nestedClassName, String methodName) { return selectNestedMethod((ClassLoader) null, enclosingClassNames, nestedClassName, methodName); } /** * Create a {@code NestedMethodSelector} for the supplied nested class name, method name, * and class loader. * * @param classLoader the class loader to use to load the method's declaring * class, or {@code null} to signal that the default {@code ClassLoader} * should be used * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @since 1.10 * @see NestedMethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName) throws PreconditionViolationException { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); return new NestedMethodSelector(classLoader, enclosingClassNames, nestedClassName, methodName, ""); } /** * Create a {@code NestedMethodSelector} for the supplied nested class name, method name, * and parameter type names. * *

The parameter type names {@code String} is typically a comma-separated * list of atomic types, fully qualified class names, or array types; however, * the exact syntax depends on the underlying test engine. * * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * parameters * @since 1.6 * @see NestedMethodSelector */ @API(status = STABLE, since = "1.6") public static NestedMethodSelector selectNestedMethod(List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { return selectNestedMethod((ClassLoader) null, enclosingClassNames, nestedClassName, methodName, parameterTypeNames); } /** * Create a {@code NestedMethodSelector} for the supplied nested class name, method name, * parameter type names, and class loader. * * @param classLoader the class loader to use to load the method's declaring * class, or {@code null} to signal that the default {@code ClassLoader} * should be used * @param enclosingClassNames the names of the enclosing classes; never {@code null} or empty * @param nestedClassName the name of the nested class to select; never {@code null} or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * parameters * @since 1.10 * @see #selectNestedMethod(List, String, String, String) */ @API(status = EXPERIMENTAL, since = "1.10") public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypeNames, "Parameter types must not be null"); return new NestedMethodSelector(classLoader, enclosingClassNames, nestedClassName, methodName, parameterTypeNames.trim()); } /** * Create a {@code NestedMethodSelector} for the supplied enclosing class names, * nested class name, method name, and parameter types. * * @param enclosingClassNames the names of the enclosing classes; never {@code null} * or empty * @param nestedClassName the name of the nested class to select; never {@code null} * or blank * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypes the formal parameter types of the method; never {@code null} * though potentially empty if the method does not declare parameters * @since 1.10 * @see NestedMethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static NestedMethodSelector selectNestedMethod(List enclosingClassNames, String nestedClassName, String methodName, Class... parameterTypes) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypes, "Parameter types array must not be null"); Preconditions.containsNoNullElements(parameterTypes, "Parameter types array must not contain null elements"); return new NestedMethodSelector((ClassLoader) null, enclosingClassNames, nestedClassName, methodName, parameterTypes); } /** * Create a {@code NestedMethodSelector} for the supplied nested {@link Class} and method name. * * @param enclosingClasses the path to the nested class to select; never {@code null} or empty * @param nestedClass the nested class to select; never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @since 1.6 * @see NestedMethodSelector */ @API(status = STABLE, since = "1.6") public static NestedMethodSelector selectNestedMethod(List> enclosingClasses, Class nestedClass, String methodName) { return selectNestedMethod(enclosingClasses, nestedClass, methodName, ""); } /** * Create a {@code NestedMethodSelector} for the supplied {@link Class}, method name, * and parameter type names. * *

The parameter type names {@code String} is typically a comma-separated * list of atomic types, fully qualified class names, or array types; however, * the exact syntax depends on the underlying test engine. * * @param enclosingClasses the path to the nested class to select; never {@code null} or empty * @param nestedClass the nested class to select; never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypeNames the parameter type names as a single string; never * {@code null} though potentially an empty string if the method does not declare * parameters * @since 1.6 * @see NestedMethodSelector */ @API(status = STABLE, since = "1.6") public static NestedMethodSelector selectNestedMethod(List> enclosingClasses, Class nestedClass, String methodName, String parameterTypeNames) { Preconditions.notEmpty(enclosingClasses, "Enclosing classes must not be null or empty"); Preconditions.notNull(nestedClass, "Nested class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypeNames, "Parameter types must not be null"); return new NestedMethodSelector(enclosingClasses, nestedClass, methodName, parameterTypeNames.trim()); } /** * Create a {@code NestedMethodSelector} for the supplied enclosing classes, * nested class, method name, and parameter types. * * @param enclosingClasses the path to the nested class to select; never {@code null} * or empty * @param nestedClass the nested class to select; never {@code null} * @param methodName the name of the method to select; never {@code null} or blank * @param parameterTypes the formal parameter types of the method; never {@code null} * though potentially empty if the method does not declare parameters * @since 1.10 * @see NestedMethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") public static NestedMethodSelector selectNestedMethod(List> enclosingClasses, Class nestedClass, String methodName, Class... parameterTypes) { Preconditions.notEmpty(enclosingClasses, "Enclosing classes must not be null or empty"); Preconditions.notNull(nestedClass, "Nested class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); Preconditions.notNull(parameterTypes, "Parameter types array must not be null"); Preconditions.containsNoNullElements(parameterTypes, "Parameter types array must not contain null elements"); return new NestedMethodSelector(enclosingClasses, nestedClass, methodName, parameterTypes); } /** * Create a {@code NestedMethodSelector} for the supplied nested {@link Class} and {@link Method}. * * @param enclosingClasses the path to the nested class to select; never {@code null} or empty * @param nestedClass the nested class to select; never {@code null} * @param method the method to select; never {@code null} * @since 1.6 * @see NestedMethodSelector */ @API(status = STABLE, since = "1.6") public static NestedMethodSelector selectNestedMethod(List> enclosingClasses, Class nestedClass, Method method) { Preconditions.notEmpty(enclosingClasses, "Enclosing classes must not be null or empty"); Preconditions.notNull(nestedClass, "Nested class must not be null"); Preconditions.notNull(method, "Method must not be null"); return new NestedMethodSelector(enclosingClasses, nestedClass, method); } /** * Create a {@code UniqueIdSelector} for the supplied {@link UniqueId}. * * @param uniqueId the {@code UniqueId} to select; never {@code null} * @see UniqueIdSelector */ public static UniqueIdSelector selectUniqueId(UniqueId uniqueId) { Preconditions.notNull(uniqueId, "UniqueId must not be null"); return new UniqueIdSelector(uniqueId); } /** * Create a {@code UniqueIdSelector} for the supplied unique ID. * * @param uniqueId the unique ID to select; never {@code null} or blank * @see UniqueIdSelector */ public static UniqueIdSelector selectUniqueId(String uniqueId) { Preconditions.notBlank(uniqueId, "Unique ID must not be null or blank"); return new UniqueIdSelector(UniqueId.parse(uniqueId)); } /** * Create an {@code IterationSelector} for the supplied parent selector and * iteration indices. * * @param parentSelector the parent selector to select iterations for; never * {@code null} * @param iterationIndices the iteration indices to select; never * {@code null} or empty * @since 1.9 * @see IterationSelector */ @API(status = EXPERIMENTAL, since = "1.9") public static IterationSelector selectIteration(DiscoverySelector parentSelector, int... iterationIndices) { Preconditions.notNull(parentSelector, "Parent selector must not be null"); Preconditions.notEmpty(iterationIndices, "iteration indices must not be empty"); return new IterationSelector(parentSelector, iterationIndices); } } ExcludeClassNameFilter.java000066400000000000000000000036221455764576500362360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.included; import java.util.function.Predicate; import java.util.regex.Pattern; import org.junit.platform.engine.FilterResult; /** * {@link ClassNameFilter} that matches fully qualified class names against * patterns in the form of regular expressions. * *

If the fully qualified name of a class matches against at least one * pattern, the class will be excluded. * * @since 1.0 */ class ExcludeClassNameFilter extends AbstractClassNameFilter { ExcludeClassNameFilter(String... patterns) { super(patterns); } @Override public FilterResult apply(String className) { return findMatchingPattern(className) // .map(pattern -> excluded(formatExclusionReason(className, pattern))) // .orElseGet(() -> included(formatInclusionReason(className))); } private String formatInclusionReason(String className) { return String.format("Class name [%s] does not match any excluded pattern: %s", className, patternDescription); } private String formatExclusionReason(String className, Pattern pattern) { return String.format("Class name [%s] matches excluded pattern: '%s'", className, pattern); } @Override public Predicate toPredicate() { return className -> !findMatchingPattern(className).isPresent(); } @Override public String toString() { return String.format("%s that excludes class names that match one of the following regular expressions: %s", getClass().getSimpleName(), this.patternDescription); } } ExcludePackageNameFilter.java000066400000000000000000000053561455764576500365320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.joining; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.included; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.FilterResult; /** * {@link PackageNameFilter} that matches fully qualified package names that * are not prefixed by one of the package names provided to the filter. * *

If the fully qualified name of a package starts with at least one of the * packages names of the filter, the package will be excluded. * * @since 1.0 */ class ExcludePackageNameFilter implements PackageNameFilter { private final List packageNames; private final String patternDescription; ExcludePackageNameFilter(String... packageNames) { Preconditions.notEmpty(packageNames, "packageNames must not be null or empty"); Preconditions.containsNoNullElements(packageNames, "packageNames must not contain null elements"); this.packageNames = Arrays.asList(packageNames); this.patternDescription = Arrays.stream(packageNames).collect(joining("' OR '", "'", "'")); } @Override public FilterResult apply(String packageName) { return findMatchingName(packageName) // .map(matchedName -> excluded(formatExclusionReason(packageName, matchedName))) // .orElseGet(() -> included(formatInclusionReason(packageName))); } private String formatInclusionReason(String packageName) { return String.format("Package name [%s] does not match any excluded names: %s", packageName, this.patternDescription); } private String formatExclusionReason(String packageName, String matchedName) { return String.format("Package name [%s] matches excluded name: '%s'", packageName, matchedName); } @Override public Predicate toPredicate() { return packageName -> !findMatchingName(packageName).isPresent(); } private Optional findMatchingName(String packageName) { return this.packageNames.stream().filter( name -> name.equals(packageName) || packageName.startsWith(name + ".")).findAny(); } @Override public String toString() { return String.format( "%s that excludes packages whose names are either equal to or start with one of the following: %s", getClass().getSimpleName(), this.patternDescription); } } FilePosition.java000066400000000000000000000121011455764576500343040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serializable; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.ToStringBuilder; /** * Position inside a file represented by {@linkplain #getLine line} and * {@linkplain #getColumn column} numbers. * * @implNote This class is a copy of * {@link org.junit.platform.engine.support.descriptor.FilePosition FilePosition}, * which is not accessible from this package. The decision to duplicate it is * motivated by an eventual divergence between the two classes in the future. * * @since 1.7 */ @API(status = STABLE, since = "1.7") public class FilePosition implements Serializable { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(FilePosition.class); /** * Create a new {@code FilePosition} using the supplied {@code line} number * and an undefined column number. * * @param line the line number; must be greater than zero * @return a {@link FilePosition} with the given line number */ public static FilePosition from(int line) { return new FilePosition(line); } /** * Create a new {@code FilePosition} using the supplied {@code line} and * {@code column} numbers. * * @param line the line number; must be greater than zero * @param column the column number; must be greater than zero * @return a {@link FilePosition} with the given line and column numbers */ public static FilePosition from(int line, int column) { return new FilePosition(line, column); } /** * Create an optional {@code FilePosition} by parsing the supplied * {@code query} string. * *

Examples of valid {@code query} strings: *

    *
  • {@code "line=23"}
  • *
  • {@code "line=23&column=42"}
  • *
* * @param query the query string; may be {@code null} * @return an {@link Optional} containing a {@link FilePosition} with * the parsed line and column numbers; never {@code null} but potentially * empty * @since 1.3 * @see #from(int) * @see #from(int, int) */ public static Optional fromQuery(String query) { FilePosition result = null; Integer line = null; Integer column = null; if (StringUtils.isNotBlank(query)) { try { for (String pair : query.split("&")) { String[] data = pair.split("="); if (data.length == 2) { String key = data[0]; if (line == null && "line".equals(key)) { line = Integer.valueOf(data[1]); } else if (column == null && "column".equals(key)) { column = Integer.valueOf(data[1]); } } // Already found what we're looking for? if (line != null && column != null) { break; } } } catch (IllegalArgumentException ex) { logger.debug(ex, () -> "Failed to parse 'line' and/or 'column' from query string: " + query); // fall-through and continue } if (line != null) { result = column == null ? new FilePosition(line) : new FilePosition(line, column); } } return Optional.ofNullable(result); } private final int line; private final Integer column; private FilePosition(int line) { Preconditions.condition(line > 0, "line number must be greater than zero"); this.line = line; this.column = null; } private FilePosition(int line, int column) { Preconditions.condition(line > 0, "line number must be greater than zero"); Preconditions.condition(column > 0, "column number must be greater than zero"); this.line = line; this.column = column; } /** * Get the line number of this {@code FilePosition}. * * @return the line number */ public int getLine() { return this.line; } /** * Get the column number of this {@code FilePosition}, if available. * * @return an {@code Optional} containing the column number; never * {@code null} but potentially empty */ public Optional getColumn() { return Optional.ofNullable(this.column); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FilePosition that = (FilePosition) o; return (this.line == that.line) && Objects.equals(this.column, that.column); } @Override public int hashCode() { return Objects.hash(this.line, this.column); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("line", this.line) .append("column", getColumn().orElse(-1)) .toString(); // @formatter:on } } FileSelector.java000066400000000000000000000054071455764576500342730ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a file so that * {@link org.junit.platform.engine.TestEngine TestEngines} * can discover tests or containers based on files in the * file system. * * @since 1.0 * @see DiscoverySelectors#selectFile(String) * @see DiscoverySelectors#selectFile(File) * @see DirectorySelector * @see #getFile() * @see #getPath() * @see #getRawPath() */ @API(status = STABLE, since = "1.0") public class FileSelector implements DiscoverySelector { private final String path; private final FilePosition position; FileSelector(String path, FilePosition position) { this.path = path; this.position = position; } /** * Get the selected file as a {@link java.io.File}. * * @see #getPath() * @see #getRawPath() */ public File getFile() { return new File(this.path); } /** * Get the selected file as a {@link java.nio.file.Path} using the * {@linkplain FileSystems#getDefault default} {@link FileSystem}. * * @see #getFile() * @see #getRawPath() */ public Path getPath() { return Paths.get(this.path); } /** * Get the selected file as a raw path. * * @see #getFile() * @see #getPath() */ public String getRawPath() { return this.path; } /** * Get the selected position within the file as a {@link FilePosition}. */ public Optional getPosition() { return Optional.ofNullable(this.position); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FileSelector that = (FileSelector) o; return Objects.equals(this.path, that.path) && Objects.equals(this.position, that.position); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return Objects.hash(path, position); } @Override public String toString() { return new ToStringBuilder(this).append("path", this.path).append("position", this.position).toString(); } } IncludeClassNameFilter.java000066400000000000000000000036311455764576500362300ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.included; import java.util.function.Predicate; import java.util.regex.Pattern; import org.junit.platform.engine.FilterResult; /** * {@link ClassNameFilter} that matches fully qualified class names against * patterns in the form of regular expressions. * *

If the fully qualified name of a class matches against at least one * pattern, the class will be included. * * @since 1.0 */ class IncludeClassNameFilter extends AbstractClassNameFilter { IncludeClassNameFilter(String... patterns) { super(patterns); } @Override public FilterResult apply(String className) { return findMatchingPattern(className) // .map(pattern -> included(formatInclusionReason(className, pattern))) // .orElseGet(() -> excluded(formatExclusionReason(className))); } private String formatInclusionReason(String className, Pattern pattern) { return String.format("Class name [%s] matches included pattern: '%s'", className, pattern); } private String formatExclusionReason(String className) { return String.format("Class name [%s] does not match any included pattern: %s", className, this.patternDescription); } @Override public Predicate toPredicate() { return className -> findMatchingPattern(className).isPresent(); } @Override public String toString() { return String.format("%s that includes class names that match one of the following regular expressions: %s", getClass().getSimpleName(), this.patternDescription); } } IncludePackageNameFilter.java000066400000000000000000000053541455764576500365220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.joining; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.included; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.FilterResult; /** * {@link PackageNameFilter} that matches fully qualified package names that * are prefixed by one of the package names provided to the filter. * *

If the fully qualified name of a package starts with at least one of the * packages names of the filter, the package will be included. * * @since 1.0 */ class IncludePackageNameFilter implements PackageNameFilter { private final List packageNames; private final String patternDescription; IncludePackageNameFilter(String... packageNames) { Preconditions.notEmpty(packageNames, "packageNames array must not be null or empty"); Preconditions.containsNoNullElements(packageNames, "packageNames array must not contain null elements"); this.packageNames = Arrays.asList(packageNames); this.patternDescription = Arrays.stream(packageNames).collect(joining("' OR '", "'", "'")); } @Override public FilterResult apply(String packageName) { return findMatchingName(packageName) // .map(matchedName -> included(formatInclusionReason(packageName, matchedName))) // .orElseGet(() -> excluded(formatExclusionReason(packageName))); } private String formatInclusionReason(String packageName, String matchedName) { return String.format("Package name [%s] matches included name: '%s'", packageName, matchedName); } private String formatExclusionReason(String packageName) { return String.format("Package name [%s] does not match any included names: %s", packageName, this.patternDescription); } @Override public Predicate toPredicate() { return packageName -> findMatchingName(packageName).isPresent(); } private Optional findMatchingName(String packageName) { return this.packageNames.stream().filter( name -> name.equals(packageName) || packageName.startsWith(name + ".")).findAny(); } @Override public String toString() { return String.format( "%s that includes packages whose names are either equal to or start with one of the following: %s", getClass().getSimpleName(), this.patternDescription); } } IterationSelector.java000066400000000000000000000052171455764576500353510ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toCollection; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.util.Arrays; import java.util.Collections; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects the iterations of a parent * {@code DiscoverySelector} via their indices so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * a subset of the iterations of tests or containers. * * @since 1.9 * @see DiscoverySelectors#selectIteration(DiscoverySelector, int...) */ @API(status = EXPERIMENTAL, since = "1.9") public class IterationSelector implements DiscoverySelector { private final DiscoverySelector parentSelector; private final SortedSet iterationIndices; IterationSelector(DiscoverySelector parentSelector, int... iterationIndices) { this.parentSelector = parentSelector; this.iterationIndices = toSortedSet(iterationIndices); } private SortedSet toSortedSet(int[] iterationIndices) { return Arrays.stream(iterationIndices) // .boxed() // .collect(collectingAndThen(toCollection(TreeSet::new), Collections::unmodifiableSortedSet)); } /** * Get the selected parent {@link DiscoverySelector}. */ public DiscoverySelector getParentSelector() { return parentSelector; } /** * Get the selected iteration indices. */ public SortedSet getIterationIndices() { return iterationIndices; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } IterationSelector that = (IterationSelector) o; return parentSelector.equals(that.parentSelector) && iterationIndices.equals(that.iterationIndices); } @Override public int hashCode() { return Objects.hash(parentSelector, iterationIndices); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("parentSelector", this.parentSelector) .append("iterationIndices", this.iterationIndices) .toString(); // @formatter:on } } MethodSelector.java000066400000000000000000000244511455764576500346340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a {@link Method} or a combination of * class name, method name, and parameter types so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover tests * or containers based on methods. * *

If a Java {@link Method} is provided, the selector will return that * {@linkplain #getJavaMethod() method} and its method name, class name, and * parameter types accordingly. If a {@link Class} and method name, a class name * and method name, or a fully qualified method name is provided, * this selector will only attempt to lazily load the class, method, or parameter * types if {@link #getJavaClass()}, {@link #getJavaMethod()}, or * {@link #getParameterTypes()} is invoked. * *

In this context, a Java {@code Method} means anything that can be referenced * as a {@link Method} on the JVM — for example, methods from Java classes * or methods from other JVM languages such Groovy, Scala, etc. * * @since 1.0 * @see DiscoverySelectors#selectMethod(String) * @see DiscoverySelectors#selectMethod(String, String) * @see DiscoverySelectors#selectMethod(String, String, String) * @see DiscoverySelectors#selectMethod(Class, String) * @see DiscoverySelectors#selectMethod(Class, String, String) * @see DiscoverySelectors#selectMethod(Class, Method) * @see org.junit.platform.engine.support.descriptor.MethodSource */ @API(status = STABLE, since = "1.0") public class MethodSelector implements DiscoverySelector { private final ClassLoader classLoader; private final String className; private final String methodName; private final String parameterTypeNames; private volatile Class javaClass; private volatile Method javaMethod; private volatile Class[] parameterTypes; /** * @since 1.10 */ MethodSelector(ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { this.classLoader = classLoader; this.className = className; this.methodName = methodName; this.parameterTypeNames = parameterTypeNames; } MethodSelector(Class javaClass, String methodName, String parameterTypeNames) { this.classLoader = javaClass.getClassLoader(); this.javaClass = javaClass; this.className = javaClass.getName(); this.methodName = methodName; this.parameterTypeNames = parameterTypeNames; } /** * @since 1.10 */ MethodSelector(ClassLoader classLoader, String className, String methodName, Class... parameterTypes) { this.classLoader = classLoader; this.className = className; this.methodName = methodName; this.parameterTypes = parameterTypes.clone(); this.parameterTypeNames = ClassUtils.nullSafeToString(Class::getTypeName, this.parameterTypes); } /** * @since 1.10 */ MethodSelector(Class javaClass, String methodName, Class... parameterTypes) { this.classLoader = javaClass.getClassLoader(); this.javaClass = javaClass; this.className = javaClass.getName(); this.methodName = methodName; this.parameterTypes = parameterTypes.clone(); this.parameterTypeNames = ClassUtils.nullSafeToString(Class::getTypeName, this.parameterTypes); } MethodSelector(Class javaClass, Method method) { this.classLoader = javaClass.getClassLoader(); this.javaClass = javaClass; this.className = javaClass.getName(); this.javaMethod = method; this.methodName = method.getName(); this.parameterTypes = method.getParameterTypes(); this.parameterTypeNames = ClassUtils.nullSafeToString(Class::getTypeName, this.parameterTypes); } /** * Get the {@link ClassLoader} used to load the specified class. * * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.classLoader; } /** * Get the selected class name. */ public String getClassName() { return this.className; } /** * Get the selected method name. */ public String getMethodName() { return this.methodName; } /** * Get the names of parameter types for the selected method. * *

See {@link #getParameterTypeNames()} for details. * * @return the names of parameter types * @since 1.0 * @see #getParameterTypeNames() * @see #getParameterTypes() * @deprecated since 1.10 in favor of {@link #getParameterTypeNames()} */ @Deprecated @API(status = DEPRECATED, since = "1.10") public String getMethodParameterTypes() { return getParameterTypeNames(); } /** * Get the names of parameter types for the selected method as a {@link String}, * typically a comma-separated list of primitive types, fully qualified class * names, or array types. * *

Note: the names of parameter types are provided as a single string instead * of a collection in order to allow this selector to be used in a generic * fashion by various test engines. It is therefore the responsibility of * the caller of this method to determine how to parse the returned string. * * @return the names of parameter types supplied to this {@code MethodSelector} * via a constructor or deduced from a {@code Method} or parameter types supplied * via a constructor; never {@code null} but potentially an empty string * @since 1.10 * @see #getParameterTypes() */ @API(status = STABLE, since = "1.10") public String getParameterTypeNames() { return this.parameterTypeNames; } /** * Get the {@link Class} in which the selected {@linkplain #getJavaMethod * method} is declared, or a subclass thereof. * *

If the {@link Class} was not provided, but only the name, this method * attempts to lazily load the {@code Class} based on its name and throws a * {@link PreconditionViolationException} if the class cannot be loaded. * * @see #getJavaMethod() */ public Class getJavaClass() { lazyLoadJavaClass(); return this.javaClass; } /** * Get the selected {@link Method}. * *

If the {@link Method} was not provided, but only the name, this method * attempts to lazily load the {@code Method} based on its name and throws a * {@link PreconditionViolationException} if the method cannot be loaded. * * @see #getJavaClass() */ public Method getJavaMethod() { lazyLoadJavaMethod(); return this.javaMethod; } /** * Get the parameter types for the selected method. * *

If the parameter types were not provided as {@link Class} references * (or could not be deduced as {@code Class} references in the constructor), * this method attempts to lazily load the class reference for each parameter * type based on its name and throws a {@link JUnitException} if the class * cannot be loaded. * * @return the method's parameter types; never {@code null} but potentially * an empty array if the selected method does not declare parameters * @since 1.10 * @see #getParameterTypeNames() * @see Method#getParameterTypes() */ @API(status = EXPERIMENTAL, since = "1.10") public Class[] getParameterTypes() { lazyLoadParameterTypes(); return this.parameterTypes.clone(); } private void lazyLoadJavaClass() { // @formatter:off if (this.javaClass == null) { Try> tryToLoadClass = this.classLoader == null ? ReflectionUtils.tryToLoadClass(this.className) : ReflectionUtils.tryToLoadClass(this.className, this.classLoader); this.javaClass = tryToLoadClass.getOrThrow(cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); } // @formatter:on } private void lazyLoadJavaMethod() { if (this.javaMethod == null) { lazyLoadJavaClass(); lazyLoadParameterTypes(); if (this.parameterTypes.length > 0) { this.javaMethod = ReflectionUtils.findMethod(this.javaClass, this.methodName, this.parameterTypes).orElseThrow( () -> new PreconditionViolationException(String.format( "Could not find method with name [%s] and parameter types [%s] in class [%s].", this.methodName, this.parameterTypeNames, this.javaClass.getName()))); } else { this.javaMethod = ReflectionUtils.findMethod(this.javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( String.format("Could not find method with name [%s] in class [%s].", this.methodName, this.javaClass.getName()))); } } } private void lazyLoadParameterTypes() { if (this.parameterTypes == null) { lazyLoadJavaClass(); this.parameterTypes = ReflectionUtils.resolveParameterTypes(this.javaClass, this.methodName, this.parameterTypeNames); } } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MethodSelector that = (MethodSelector) o; return Objects.equals(this.className, that.className)// && Objects.equals(this.methodName, that.methodName)// && Objects.equals(this.parameterTypeNames, that.parameterTypeNames); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return Objects.hash(this.className, this.methodName, this.parameterTypeNames); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("className", getClassName()) .append("methodName", getMethodName()) .append("parameterTypes", getParameterTypeNames()) .append("classLoader", getClassLoader()) .toString(); // @formatter:on } } ModuleSelector.java000066400000000000000000000034071455764576500346370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a module name so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on modules. * * @since 1.1 * @see DiscoverySelectors#selectModule(String) * @see DiscoverySelectors#selectModules(java.util.Set) */ @API(status = STABLE, since = "1.1") public class ModuleSelector implements DiscoverySelector { private final String moduleName; ModuleSelector(String moduleName) { this.moduleName = moduleName; } /** * Get the selected module name. */ public String getModuleName() { return this.moduleName; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ModuleSelector that = (ModuleSelector) o; return Objects.equals(this.moduleName, that.moduleName); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.moduleName.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("moduleName", this.moduleName).toString(); } } NestedClassSelector.java000066400000000000000000000120371455764576500356210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.util.List; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a nested {@link Class} * or class name enclosed in other classes so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on classes. * *

If Java {@link Class} references are provided for the nested class or * the enclosing classes, the selector will return those classes and their class * names accordingly. If class names are provided, the selector will only attempt * to lazily load classes if {@link #getEnclosingClasses()} or * {@link #getNestedClass()} is invoked. * *

In this context, Java {@link Class} means anything that can be referenced * as a {@link Class} on the JVM — for example, classes from other JVM * languages such Groovy, Scala, etc. * * @since 1.6 * @see DiscoverySelectors#selectNestedClass(List, Class) * @see DiscoverySelectors#selectNestedClass(List, String) * @see org.junit.platform.engine.support.descriptor.ClassSource * @see ClassSelector */ @API(status = STABLE, since = "1.6") public class NestedClassSelector implements DiscoverySelector { private final ClassLoader classLoader; private final List enclosingClassSelectors; private final ClassSelector nestedClassSelector; NestedClassSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName) { this.classLoader = classLoader; this.enclosingClassSelectors = enclosingClassNames.stream() // .map(className -> new ClassSelector(classLoader, className)) // .collect(toUnmodifiableList()); this.nestedClassSelector = new ClassSelector(classLoader, nestedClassName); } NestedClassSelector(List> enclosingClasses, Class nestedClass) { this.classLoader = nestedClass.getClassLoader(); this.enclosingClassSelectors = enclosingClasses.stream().map(ClassSelector::new).collect(toList()); this.nestedClassSelector = new ClassSelector(nestedClass); } /** * Get the {@link ClassLoader} used to load the selected nested class. * * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.classLoader; } /** * Get the names of the classes enclosing the selected nested class. */ public List getEnclosingClassNames() { return this.enclosingClassSelectors.stream().map(ClassSelector::getClassName).collect(toList()); } /** * Get the list of {@link Class} enclosing the selected nested * {@link Class}. * *

If the {@link Class} were not provided, but only the name of the * nested class and its enclosing classes, this method attempts to lazily * load the list of enclosing {@link Class} and throws a * {@link PreconditionViolationException} if the classes cannot be loaded. */ public List> getEnclosingClasses() { return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).collect(toList()); } /** * Get the name of the selected nested class. */ public String getNestedClassName() { return this.nestedClassSelector.getClassName(); } /** * Get the selected nested {@link Class}. * *

If the {@link Class} were not provided, but only the name of the * nested class and its enclosing classes, this method attempts to lazily * load the nested {@link Class} and throws a * {@link PreconditionViolationException} if the class cannot be loaded. */ public Class getNestedClass() { return this.nestedClassSelector.getJavaClass(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } NestedClassSelector that = (NestedClassSelector) o; return this.enclosingClassSelectors.equals(that.enclosingClassSelectors) && this.nestedClassSelector.equals(that.nestedClassSelector); } @Override public int hashCode() { return Objects.hash(this.enclosingClassSelectors, this.nestedClassSelector); } @Override public String toString() { return new ToStringBuilder(this) // .append("enclosingClassNames", getEnclosingClassNames()) // .append("nestedClassName", getNestedClassName()) // .append("classLoader", getClassLoader()) // .toString(); } } NestedMethodSelector.java000066400000000000000000000207151455764576500357760ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; import java.util.List; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a nested {@link Method} * or a combination of enclosing classes names, class name, method * name, and parameter types so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on methods. * *

If a Java {@link Method} is provided, the selector will return that * {@linkplain #getMethod() method} and its method name, class name, enclosing * classes names, and parameter types accordingly. If class names or method names * are provided, this selector will only attempt to lazily load a class or method * if {@link #getEnclosingClasses()}, {@link #getNestedClass()}, * {@link #getMethod()}, or {@link #getParameterTypes()} is invoked. * *

In this context, a Java {@code Method} means anything that can be referenced * as a {@link Method} on the JVM — for example, methods from Java classes * or methods from other JVM languages such Groovy, Scala, etc. * * @since 1.6 * @see DiscoverySelectors#selectNestedMethod(List, String, String) * @see DiscoverySelectors#selectNestedMethod(List, String, String, String) * @see DiscoverySelectors#selectNestedMethod(List, Class, String) * @see DiscoverySelectors#selectNestedMethod(List, Class, String, String) * @see DiscoverySelectors#selectNestedMethod(List, Class, Method) * @see org.junit.platform.engine.support.descriptor.MethodSource * @see NestedClassSelector * @see MethodSelector */ @API(status = STABLE, since = "1.6") public class NestedMethodSelector implements DiscoverySelector { private final NestedClassSelector nestedClassSelector; private final MethodSelector methodSelector; NestedMethodSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { this.nestedClassSelector = new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); this.methodSelector = new MethodSelector(classLoader, nestedClassName, methodName, parameterTypeNames); } /** * @since 1.10 */ NestedMethodSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, Class... parameterTypes) { this.nestedClassSelector = new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); this.methodSelector = new MethodSelector(classLoader, nestedClassName, methodName, parameterTypes); } NestedMethodSelector(List> enclosingClasses, Class nestedClass, String methodName, String parameterTypeNames) { this.nestedClassSelector = new NestedClassSelector(enclosingClasses, nestedClass); this.methodSelector = new MethodSelector(nestedClass, methodName, parameterTypeNames); } /** * @since 1.10 */ NestedMethodSelector(List> enclosingClasses, Class nestedClass, String methodName, Class... parameterTypes) { this.nestedClassSelector = new NestedClassSelector(enclosingClasses, nestedClass); this.methodSelector = new MethodSelector(nestedClass, methodName, parameterTypes); } NestedMethodSelector(List> enclosingClasses, Class nestedClass, Method method) { this.nestedClassSelector = new NestedClassSelector(enclosingClasses, nestedClass); this.methodSelector = new MethodSelector(nestedClass, method); } /** * Get the {@link ClassLoader} used to load the nested class. * * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.nestedClassSelector.getClassLoader(); } /** * Get the names of the classes enclosing the nested class * containing the selected method. */ public List getEnclosingClassNames() { return this.nestedClassSelector.getEnclosingClassNames(); } /** * Get the list of {@link Class} enclosing the nested {@link Class} * containing the selected {@link Method}. * *

If the {@link Class} were not provided, but only the name of the * nested class and its enclosing classes, this method attempts to lazily * load the list of enclosing {@link Class} and throws a * {@link PreconditionViolationException} if the classes cannot be loaded. */ public List> getEnclosingClasses() { return this.nestedClassSelector.getEnclosingClasses(); } /** * Get the name of the nested class containing the selected method. */ public String getNestedClassName() { return this.nestedClassSelector.getNestedClassName(); } /** * Get the nested {@link Class} containing the selected {@link Method}. * *

If the {@link Class} were not provided, but only the name of the * nested class and its enclosing classes, this method attempts to lazily * load the nested {@link Class} and throws a * {@link PreconditionViolationException} if the class cannot be loaded. */ public Class getNestedClass() { return this.nestedClassSelector.getNestedClass(); } /** * Get the name of the selected method. */ public String getMethodName() { return this.methodSelector.getMethodName(); } /** * Get the selected {@link Method}. * *

If the {@link Method} was not provided, but only the name, this method * attempts to lazily load the {@code Method} based on its name and throws a * {@link PreconditionViolationException} if the method cannot be loaded. */ public Method getMethod() { return this.methodSelector.getJavaMethod(); } /** * Get the names of parameter types for the selected method. * *

See {@link #getParameterTypeNames()} for details. * * @return the names of parameter types * @since 1.6 * @see #getParameterTypeNames() * @see #getParameterTypes() * @deprecated since 1.10 in favor or {@link #getParameterTypeNames()} */ @Deprecated @API(status = DEPRECATED, since = "1.10") public String getMethodParameterTypes() { return getParameterTypeNames(); } /** * Get the names of parameter types for the selected method as a {@link String}. * *

See {@link MethodSelector#getParameterTypeNames()} for details. * * @return the names of parameter types supplied to this {@code NestedMethodSelector} * via a constructor or deduced from a {@code Method} or parameter types supplied * via a constructor; never {@code null} but potentially an empty string * @since 1.10 * @see MethodSelector#getParameterTypeNames() * */ @API(status = STABLE, since = "1.10") public String getParameterTypeNames() { return this.methodSelector.getParameterTypeNames(); } /** * Get the parameter types for the selected method. * *

See {@link MethodSelector#getParameterTypes()} for details. * * @return the method's parameter types; never {@code null} but potentially * an empty array if the selected method does not declare parameters * @since 1.10 * @see #getParameterTypeNames() * @see MethodSelector#getParameterTypes() */ @API(status = EXPERIMENTAL, since = "1.10") public Class[] getParameterTypes() { return this.methodSelector.getParameterTypes(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } NestedMethodSelector that = (NestedMethodSelector) o; return this.nestedClassSelector.equals(that.nestedClassSelector) && this.methodSelector.equals(that.methodSelector); } @Override public int hashCode() { return Objects.hash(this.nestedClassSelector, this.methodSelector); } @Override public String toString() { return new ToStringBuilder(this) // .append("enclosingClassNames", getEnclosingClassNames()) // .append("nestedClassName", getNestedClassName()) // .append("methodName", getMethodName()) // .append("parameterTypes", getParameterTypeNames()) // .append("classLoader", getClassLoader()) // .toString(); } } PackageNameFilter.java000066400000000000000000000070051455764576500352110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.engine.DiscoveryFilter; /** * {@link DiscoveryFilter} that is applied to the name of a {@link Package}. * * @since 1.0 * @see #includePackageNames(String...) * @see #excludePackageNames(String...) * @see ClassNameFilter */ @API(status = STABLE, since = "1.0") public interface PackageNameFilter extends DiscoveryFilter { /** * Create a new include {@link PackageNameFilter} based on the * supplied package names. * *

The names are combined using OR semantics, i.e. if the fully * qualified name of a package starts with at least one of the names, * the package will be included in the result set. * * @param names package names that we be compared against fully qualified * package names; never {@code null}, empty, or containing {@code null} * @see Package#getName() * @see #includePackageNames(List) * @see #excludePackageNames(String...) */ static PackageNameFilter includePackageNames(String... names) { return new IncludePackageNameFilter(names); } /** * Create a new include {@link PackageNameFilter} based on the * supplied package names. * *

The names are combined using OR semantics, i.e. if the fully * qualified name of a package starts with at least one of the names, * the package will be included in the result set. * * @param names package names that we be compared against fully qualified * package names; never {@code null}, empty, or containing {@code null} * @see Package#getName() * @see #includePackageNames(String...) * @see #excludePackageNames(String...) */ static PackageNameFilter includePackageNames(List names) { return includePackageNames(names.toArray(new String[0])); } /** * Create a new exclude {@link PackageNameFilter} based on the * supplied package names. * *

The names are combined using OR semantics, i.e. if the fully * qualified name of a package starts with at least one of the names, * the package will be excluded in the result set. * * @param names package names that we be compared against fully qualified * package names; never {@code null}, empty, or containing {@code null} * @see Package#getName() * @see #excludePackageNames(List) * @see #includePackageNames(String...) */ static PackageNameFilter excludePackageNames(String... names) { return new ExcludePackageNameFilter(names); } /** * Create a new exclude {@link PackageNameFilter} based on the * supplied package names. * *

The names are combined using OR semantics, i.e. if the fully * qualified name of a package starts with at least one of the names, * the package will be excluded in the result set. * * @param names package names that we be compared against fully qualified * package names; never {@code null}, empty, or containing {@code null} * @see Package#getName() * @see #excludePackageNames(String...) * @see #includePackageNames(String...) */ static PackageNameFilter excludePackageNames(List names) { return excludePackageNames(names.toArray(new String[0])); } } PackageSelector.java000066400000000000000000000034451455764576500347470ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a package name so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on packages. * * @since 1.0 * @see DiscoverySelectors#selectPackage(String) * @see org.junit.platform.engine.support.descriptor.PackageSource */ @API(status = STABLE, since = "1.0") public class PackageSelector implements DiscoverySelector { private final String packageName; PackageSelector(String packageName) { this.packageName = packageName; } /** * Get the selected package name. */ public String getPackageName() { return this.packageName; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PackageSelector that = (PackageSelector) o; return Objects.equals(this.packageName, that.packageName); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.packageName.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("packageName", this.packageName).toString(); } } UniqueIdSelector.java000066400000000000000000000034651455764576500351410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.UniqueId; /** * A {@link DiscoverySelector} that selects a {@link UniqueId} so that * {@link org.junit.platform.engine.TestEngine TestEngines} can discover * tests or containers based on unique IDs. * * @since 1.0 * @see DiscoverySelectors#selectUniqueId(String) * @see DiscoverySelectors#selectUniqueId(UniqueId) */ @API(status = STABLE, since = "1.0") public class UniqueIdSelector implements DiscoverySelector { private final UniqueId uniqueId; UniqueIdSelector(UniqueId uniqueId) { this.uniqueId = uniqueId; } /** * Get the selected {@link UniqueId}. */ public UniqueId getUniqueId() { return this.uniqueId; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } UniqueIdSelector that = (UniqueIdSelector) o; return Objects.equals(this.uniqueId, that.uniqueId); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.uniqueId.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("uniqueId", this.uniqueId).toString(); } } UriSelector.java000066400000000000000000000034241455764576500341500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.STABLE; import java.net.URI; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; /** * A {@link DiscoverySelector} that selects a {@link URI} so that * {@link org.junit.platform.engine.TestEngine TestEngines} * can discover tests or containers based on URIs. * * @since 1.0 * @see DiscoverySelectors#selectUri(String) * @see DiscoverySelectors#selectUri(URI) * @see FileSelector * @see DirectorySelector * @see org.junit.platform.engine.support.descriptor.UriSource */ @API(status = STABLE, since = "1.0") public class UriSelector implements DiscoverySelector { private final URI uri; UriSelector(URI uri) { this.uri = uri; } /** * Get the selected {@link URI}. */ public URI getUri() { return this.uri; } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } UriSelector that = (UriSelector) o; return Objects.equals(this.uri, that.uri); } /** * @since 1.3 */ @API(status = STABLE, since = "1.3") @Override public int hashCode() { return this.uri.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("uri", this.uri).toString(); } } package-info.java000066400000000000000000000004561455764576500342360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/** * Concrete {@linkplain org.junit.platform.engine.DiscoverySelector selectors} and * {@linkplain org.junit.platform.engine.DiscoveryFilter filters} to be used in * {@linkplain org.junit.platform.engine.EngineDiscoveryRequest discovery requests}. */ package org.junit.platform.engine.discovery; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java000066400000000000000000000001141455764576500322750ustar00rootroot00000000000000/** * Public API for test engines. */ package org.junit.platform.engine; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/000077500000000000000000000000001455764576500311235ustar00rootroot00000000000000ReportEntry.java000066400000000000000000000063011455764576500342040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.reporting; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.time.LocalDateTime; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code ReportEntry} encapsulates a time-stamped map of {@code String}-based * key-value pairs to be published to the reporting infrastructure. * * @since 1.0 * @see #from(Map) * @see #from(String, String) */ @API(status = STABLE, since = "1.0") public final class ReportEntry { private final LocalDateTime timestamp = LocalDateTime.now(); private final Map keyValuePairs = new LinkedHashMap<>(); /** * @deprecated Use {@link #from(String, String)} or {@link #from(Map)} */ @API(status = DEPRECATED, since = "5.8") @Deprecated public ReportEntry() { } /** * Factory for creating a new {@code ReportEntry} from a map of key-value pairs. * * @param keyValuePairs the map of key-value pairs to be published; never * {@code null}; keys and values within entries in the map also must not be * {@code null} or blank */ public static ReportEntry from(Map keyValuePairs) { Preconditions.notNull(keyValuePairs, "keyValuePairs must not be null"); ReportEntry reportEntry = new ReportEntry(); keyValuePairs.forEach(reportEntry::add); return reportEntry; } /** * Factory for creating a new {@code ReportEntry} from a key-value pair. * * @param key the key under which the value should published; never * {@code null} or blank * @param value the value to publish; never {@code null} or blank */ public static ReportEntry from(String key, String value) { ReportEntry reportEntry = new ReportEntry(); reportEntry.add(key, value); return reportEntry; } private void add(String key, String value) { Preconditions.notBlank(key, "key must not be null or blank"); Preconditions.notBlank(value, "value must not be null or blank"); this.keyValuePairs.put(key, value); } /** * Get an unmodifiable copy of the map of key-value pairs to be published. * * @return a copy of the map of key-value pairs; never {@code null} */ public final Map getKeyValuePairs() { return Collections.unmodifiableMap(this.keyValuePairs); } /** * Get the timestamp for when this {@code ReportEntry} was created. * *

Can be used, for example, to order entries. * * @return when this entry was created; never {@code null} */ public final LocalDateTime getTimestamp() { return this.timestamp; } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.append("timestamp", this.timestamp); this.keyValuePairs.forEach(builder::append); return builder.toString(); } } package-info.java000066400000000000000000000002131455764576500342270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/** * Classes used by test engines to report additional data to execution * listeners. */ package org.junit.platform.engine.reporting; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/000077500000000000000000000000001455764576500306265ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/000077500000000000000000000000001455764576500320735ustar00rootroot00000000000000PrefixedConfigurationParameters.java000066400000000000000000000041251455764576500412030ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.config; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import java.util.Set; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; /** * View of {@link ConfigurationParameters} that applies a supplied prefix to all * queries. * * @since 1.3 */ @API(status = STABLE, since = "1.10") public class PrefixedConfigurationParameters implements ConfigurationParameters { private final ConfigurationParameters delegate; private final String prefix; /** * Create a new view of the supplied {@link ConfigurationParameters} that * applies the supplied prefix to all queries. * * @param delegate the {@link ConfigurationParameters} to delegate to; never * {@code null} * @param prefix the prefix to apply to all queries; never {@code null} or * blank */ public PrefixedConfigurationParameters(ConfigurationParameters delegate, String prefix) { this.delegate = Preconditions.notNull(delegate, "delegate must not be null"); this.prefix = Preconditions.notBlank(prefix, "prefix must not be null or blank"); } @Override public Optional get(String key) { return delegate.get(prefixed(key)); } @Override public Optional getBoolean(String key) { return delegate.getBoolean(prefixed(key)); } @Override public Optional get(String key, Function transformer) { return delegate.get(prefixed(key), transformer); } private String prefixed(String key) { return prefix + key; } @Override @SuppressWarnings("deprecation") public int size() { return delegate.size(); } @Override public Set keySet() { return delegate.keySet(); } } package-info.java000066400000000000000000000003071455764576500352030ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/** * {@link org.junit.platform.engine.ConfigurationParameters}-related support * classes intended to be used by test engine implementations. */ package org.junit.platform.engine.support.config; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/000077500000000000000000000000001455764576500330045ustar00rootroot00000000000000AbstractTestDescriptor.java000066400000000000000000000125251455764576500402370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static java.util.Collections.emptySet; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; /** * Abstract base implementation of {@link TestDescriptor} that may be used by * custom {@link org.junit.platform.engine.TestEngine TestEngines}. * *

Subclasses should provide a {@link TestSource} in their constructor, if * possible, and override {@link #getTags()}, if appropriate. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public abstract class AbstractTestDescriptor implements TestDescriptor { private final UniqueId uniqueId; private final String displayName; private final TestSource source; private TestDescriptor parent; /** * The synchronized set of children associated with this {@code TestDescriptor}. * *

This set is used in methods such as {@link #addChild(TestDescriptor)}, * {@link #removeChild(TestDescriptor)}, {@link #removeFromHierarchy()}, and * {@link #findByUniqueId(UniqueId)}, and an immutable copy of this set is * returned by {@link #getChildren()}. * *

If a subclass overrides any of the methods related to children, this * set should be used instead of a set local to the subclass. */ protected final Set children = Collections.synchronizedSet(new LinkedHashSet<>(16)); /** * Create a new {@code AbstractTestDescriptor} with the supplied * {@link UniqueId} and display name. * * @param uniqueId the unique ID of this {@code TestDescriptor}; never * {@code null} * @param displayName the display name for this {@code TestDescriptor}; * never {@code null} or blank * @see #AbstractTestDescriptor(UniqueId, String, TestSource) */ protected AbstractTestDescriptor(UniqueId uniqueId, String displayName) { this(uniqueId, displayName, null); } /** * Create a new {@code AbstractTestDescriptor} with the supplied * {@link UniqueId}, display name, and source. * * @param uniqueId the unique ID of this {@code TestDescriptor}; never * {@code null} * @param displayName the display name for this {@code TestDescriptor}; * never {@code null} or blank * @param source the source of the test or container described by this * {@code TestDescriptor}; can be {@code null} * @see #AbstractTestDescriptor(UniqueId, String) */ protected AbstractTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { this.uniqueId = Preconditions.notNull(uniqueId, "UniqueId must not be null"); this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or blank"); this.source = source; } @Override public final UniqueId getUniqueId() { return this.uniqueId; } @Override public final String getDisplayName() { return this.displayName; } @Override public Set getTags() { return emptySet(); } @Override public Optional getSource() { return Optional.ofNullable(this.source); } @Override public final Optional getParent() { return Optional.ofNullable(this.parent); } @Override public final void setParent(TestDescriptor parent) { this.parent = parent; } @Override public final Set getChildren() { return Collections.unmodifiableSet(this.children); } @Override public void addChild(TestDescriptor child) { Preconditions.notNull(child, "child must not be null"); child.setParent(this); this.children.add(child); } @Override public void removeChild(TestDescriptor child) { Preconditions.notNull(child, "child must not be null"); this.children.remove(child); child.setParent(null); } @Override public void removeFromHierarchy() { Preconditions.condition(!isRoot(), "cannot remove the root of a hierarchy"); this.parent.removeChild(this); this.children.forEach(child -> child.setParent(null)); this.children.clear(); } @Override public Optional findByUniqueId(UniqueId uniqueId) { Preconditions.notNull(uniqueId, "UniqueId must not be null"); if (getUniqueId().equals(uniqueId)) { return Optional.of(this); } // @formatter:off return this.children.stream() .map(child -> child.findByUniqueId(uniqueId)) .filter(Optional::isPresent) .findAny() .orElse(Optional.empty()); // @formatter:on } @Override public final int hashCode() { return this.uniqueId.hashCode(); } @Override public final boolean equals(Object other) { if (other == null) { return false; } if (this.getClass() != other.getClass()) { return false; } TestDescriptor that = (TestDescriptor) other; return this.getUniqueId().equals(that.getUniqueId()); } @Override public String toString() { return getClass().getSimpleName() + ": " + getUniqueId(); } } ClassSource.java000066400000000000000000000162071455764576500360240ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.net.URI; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestSource; /** * Class based {@link org.junit.platform.engine.TestSource TestSource} with * an optional {@linkplain FilePosition file position}. * *

If a Java {@link Class} reference is provided, the {@code ClassSource} * will contain that {@code Class} and its class name accordingly. If a class * name is provided, the {@code ClassSource} will contain the class name and * will only attempt to lazily load the {@link Class} if {@link #getJavaClass()} * is invoked. * *

In this context, Java {@link Class} means anything that can be referenced * as a {@link Class} on the JVM — for example, classes from other JVM * languages such Groovy, Scala, etc. * * @since 1.0 * @see org.junit.platform.engine.discovery.ClassSelector */ @API(status = STABLE, since = "1.0") public class ClassSource implements TestSource { private static final long serialVersionUID = 1L; /** * {@link URI} {@linkplain URI#getScheme() scheme} for class sources: {@value} * * @since 1.8 */ @API(status = STABLE, since = "1.8") public static final String CLASS_SCHEME = "class"; /** * Create a new {@code ClassSource} using the supplied class name. * * @param className the class name; must not be {@code null} or blank */ public static ClassSource from(String className) { return new ClassSource(className); } /** * Create a new {@code ClassSource} using the supplied class name and * {@linkplain FilePosition file position}. * * @param className the class name; must not be {@code null} or blank * @param filePosition the position in the source file; may be {@code null} */ public static ClassSource from(String className, FilePosition filePosition) { return new ClassSource(className, filePosition); } /** * Create a new {@code ClassSource} using the supplied {@linkplain Class class}. * * @param javaClass the Java class; must not be {@code null} */ public static ClassSource from(Class javaClass) { return new ClassSource(javaClass); } /** * Create a new {@code ClassSource} using the supplied {@linkplain Class class} * and {@linkplain FilePosition file position}. * * @param javaClass the Java class; must not be {@code null} * @param filePosition the position in the Java source file; may be {@code null} */ public static ClassSource from(Class javaClass, FilePosition filePosition) { return new ClassSource(javaClass, filePosition); } /** * Create a new {@code ClassSource} from the supplied {@link URI}. * *

URIs should be formatted as {@code class:fully.qualified.class.Name}. * The {@linkplain URI#getQuery() query} component of the {@code URI}, if * present, will be used to retrieve the {@link FilePosition} via * {@link FilePosition#fromQuery(String)}. For example, line 42 and column * 13 can be referenced in class {@code org.example.MyType} via the following * URI: {@code class:com.example.MyType?line=42&column=13}. The URI fragment, * if present, will be ignored. * * @param uri the {@code URI} for the class source; never {@code null} * @return a new {@code ClassSource}; never {@code null} * @throws PreconditionViolationException if the supplied {@code URI} is * {@code null}, if the scheme of the supplied {@code URI} is not equal * to the {@link #CLASS_SCHEME}, or if the specified class name is empty * @since 1.8 * @see #CLASS_SCHEME */ @API(status = STABLE, since = "1.8") public static ClassSource from(URI uri) { Preconditions.notNull(uri, "URI must not be null"); Preconditions.condition(CLASS_SCHEME.equals(uri.getScheme()), () -> "URI [" + uri + "] must have [" + CLASS_SCHEME + "] scheme"); String className = uri.getSchemeSpecificPart(); FilePosition filePosition = null; int indexOfQuery = className.indexOf('?'); if (indexOfQuery >= 0) { filePosition = FilePosition.fromQuery(className.substring(indexOfQuery + 1)).orElse(null); className = className.substring(0, indexOfQuery); } return ClassSource.from(className, filePosition); } private final String className; private final FilePosition filePosition; private Class javaClass; private ClassSource(String className) { this(className, null); } private ClassSource(String className, FilePosition filePosition) { this.className = Preconditions.notBlank(className, "Class name must not be null or blank"); this.filePosition = filePosition; } private ClassSource(Class javaClass) { this(javaClass, null); } private ClassSource(Class javaClass, FilePosition filePosition) { this.javaClass = Preconditions.notNull(javaClass, "Class must not be null"); this.className = this.javaClass.getName(); this.filePosition = filePosition; } /** * Get the class name of this source. * * @see #getJavaClass() * @see #getPosition() */ public final String getClassName() { return this.className; } /** * Get the {@linkplain Class Java class} of this source. * *

If the {@link Class} was not provided, but only the name, this method * attempts to lazily load the {@link Class} based on its name and throws a * {@link PreconditionViolationException} if the class cannot be loaded. * * @see #getClassName() * @see #getPosition() */ public final Class getJavaClass() { if (this.javaClass == null) { // @formatter:off this.javaClass = ReflectionUtils.tryToLoadClass(this.className).getOrThrow( cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } return this.javaClass; } /** * Get the {@linkplain FilePosition position} in the source file for * the associated {@linkplain #getClassName class}, if available. * * @see #getClassName() * @see #getJavaClass() */ public final Optional getPosition() { return Optional.ofNullable(this.filePosition); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ClassSource that = (ClassSource) o; return Objects.equals(this.className, that.className) && Objects.equals(this.filePosition, that.filePosition); } @Override public int hashCode() { return Objects.hash(this.className, this.filePosition); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("className", this.className) .append("filePosition", this.filePosition) .toString(); // @formatter:on } } ClasspathResourceSource.java000066400000000000000000000137471455764576500404170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.net.URI; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestSource; /** * Classpath resource based {@link org.junit.platform.engine.TestSource} * with an optional {@linkplain FilePosition position}. * * @since 1.0 * @see org.junit.platform.engine.discovery.ClasspathResourceSelector */ @API(status = STABLE, since = "1.0") public class ClasspathResourceSource implements TestSource { private static final long serialVersionUID = 1L; /** * {@link URI} {@linkplain URI#getScheme() scheme} for classpath * resources: {@value} * * @since 1.3 */ public static final String CLASSPATH_SCHEME = "classpath"; /** * Create a new {@code ClasspathResourceSource} using the supplied classpath * resource name. * *

The name of a classpath resource must follow the semantics * for resource paths as defined in {@link ClassLoader#getResource(String)}. * *

If the supplied classpath resource name is prefixed with a slash * ({@code /}), the slash will be removed. * * @param classpathResourceName the name of the classpath resource; never * {@code null} or blank * @see ClassLoader#getResource(String) * @see ClassLoader#getResourceAsStream(String) * @see ClassLoader#getResources(String) */ public static ClasspathResourceSource from(String classpathResourceName) { return new ClasspathResourceSource(classpathResourceName); } /** * Create a new {@code ClasspathResourceSource} using the supplied classpath * resource name and {@link FilePosition}. * *

The name of a classpath resource must follow the semantics * for resource paths as defined in {@link ClassLoader#getResource(String)}. * *

If the supplied classpath resource name is prefixed with a slash * ({@code /}), the slash will be removed. * * @param classpathResourceName the name of the classpath resource; never * {@code null} or blank * @param filePosition the position in the classpath resource; may be {@code null} */ public static ClasspathResourceSource from(String classpathResourceName, FilePosition filePosition) { return new ClasspathResourceSource(classpathResourceName, filePosition); } /** * Create a new {@code ClasspathResourceSource} from the supplied {@link URI}. * *

The {@link URI#getPath() path} component of the {@code URI} (excluding * the query) will be used as the classpath resource name. The * {@linkplain URI#getQuery() query} component of the {@code URI}, if present, * will be used to retrieve the {@link FilePosition} via * {@link FilePosition#fromQuery(String)}. * * @param uri the {@code URI} for the classpath resource; never {@code null} * @return a new {@code ClasspathResourceSource}; never {@code null} * @throws PreconditionViolationException if the supplied {@code URI} is * {@code null} or if the scheme of the supplied {@code URI} is not equal * to the {@link #CLASSPATH_SCHEME} * @since 1.3 * @see #CLASSPATH_SCHEME */ @API(status = STABLE, since = "1.3") public static ClasspathResourceSource from(URI uri) { Preconditions.notNull(uri, "URI must not be null"); Preconditions.condition(CLASSPATH_SCHEME.equals(uri.getScheme()), () -> "URI [" + uri + "] must have [" + CLASSPATH_SCHEME + "] scheme"); String classpathResource = ResourceUtils.stripQueryComponent(uri).getPath(); FilePosition filePosition = FilePosition.fromQuery(uri.getQuery()).orElse(null); return ClasspathResourceSource.from(classpathResource, filePosition); } private final String classpathResourceName; private final FilePosition filePosition; private ClasspathResourceSource(String classpathResourceName) { this(classpathResourceName, null); } private ClasspathResourceSource(String classpathResourceName, FilePosition filePosition) { Preconditions.notBlank(classpathResourceName, "Classpath resource name must not be null or blank"); boolean startsWithSlash = classpathResourceName.startsWith("/"); this.classpathResourceName = (startsWithSlash ? classpathResourceName.substring(1) : classpathResourceName); this.filePosition = filePosition; } /** * Get the name of the source classpath resource. * *

The name of a classpath resource follows the semantics for * resource paths as defined in {@link ClassLoader#getResource(String)}. * * @see ClassLoader#getResource(String) * @see ClassLoader#getResourceAsStream(String) * @see ClassLoader#getResources(String) */ public String getClasspathResourceName() { return this.classpathResourceName; } /** * Get the {@link FilePosition}, if available. */ public final Optional getPosition() { return Optional.ofNullable(this.filePosition); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ClasspathResourceSource that = (ClasspathResourceSource) o; return Objects.equals(this.classpathResourceName, that.classpathResourceName) && Objects.equals(this.filePosition, that.filePosition); } @Override public int hashCode() { return Objects.hash(this.classpathResourceName, this.filePosition); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("classpathResourceName", this.classpathResourceName) .append("filePosition", this.filePosition) .toString(); // @formatter:on } } CompositeTestSource.java000066400000000000000000000055221455764576500375570ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestSource; /** * A {@code CompositeTestSource} contains one or more {@link TestSource TestSources}. * *

{@code CompositeTestSource} and its {@link #getSources sources} are immutable. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class CompositeTestSource implements TestSource { private static final long serialVersionUID = 1L; /** * Create a new {@code CompositeTestSource} based on the supplied * collection of {@link TestSource sources}. * *

This constructor makes a defensive copy of the supplied collection * and stores the sources as a list in the order in which they are * returned by the collection's iterator. * * @param sources the collection of sources to store in this * {@code CompositeTestSource}; never {@code null} or empty */ public static CompositeTestSource from(Collection sources) { return new CompositeTestSource(sources); } @SuppressWarnings({ "serial", "RedundantSuppression" }) // always used with serializable implementation (unmodifiableList()) private final List sources; private CompositeTestSource(Collection sources) { Preconditions.notEmpty(sources, "TestSource collection must not be null or empty"); Preconditions.containsNoNullElements(sources, "individual TestSources must not be null"); this.sources = unmodifiableList(new ArrayList<>(sources)); } /** * Get an immutable list of the {@linkplain TestSource sources} stored in this * {@code CompositeTestSource}. * * @return the sources stored in this {@code CompositeTestSource}; never {@code null} */ public final List getSources() { return this.sources; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } CompositeTestSource that = (CompositeTestSource) obj; return this.sources.equals(that.sources); } @Override public int hashCode() { return this.sources.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("sources", this.sources).toString(); } } DefaultUriSource.java000066400000000000000000000024411455764576500370160ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import java.net.URI; import java.util.Objects; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * Default implementation of {@link UriSource}. * * @since 1.3 */ class DefaultUriSource implements UriSource { private static final long serialVersionUID = 1L; private final URI uri; DefaultUriSource(URI uri) { this.uri = Preconditions.notNull(uri, "URI must not be null"); } @Override public URI getUri() { return uri; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DefaultUriSource that = (DefaultUriSource) o; return Objects.equals(this.uri, that.uri); } @Override public int hashCode() { return this.uri.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("uri", this.uri).toString(); } } DirectorySource.java000066400000000000000000000046261455764576500367250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import java.io.IOException; import java.net.URI; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * Directory based {@link org.junit.platform.engine.TestSource}. * * @since 1.0 * @see org.junit.platform.engine.discovery.DirectorySelector */ @API(status = STABLE, since = "1.0") public class DirectorySource implements FileSystemSource { private static final long serialVersionUID = 1L; /** * Create a new {@code DirectorySource} using the supplied * {@linkplain File directory}. * * @param directory the source directory; must not be {@code null} */ public static DirectorySource from(File directory) { return new DirectorySource(directory); } private final File directory; private DirectorySource(File directory) { Preconditions.notNull(directory, "directory must not be null"); try { this.directory = directory.getCanonicalFile(); } catch (IOException ex) { throw new JUnitException("Failed to retrieve canonical path for directory: " + directory, ex); } } /** * Get the {@link URI} for the source {@linkplain #getFile directory}. * * @return the source {@code URI}; never {@code null} */ @Override public final URI getUri() { return getFile().toURI(); } /** * Get the source {@linkplain File directory}. * * @return the source directory; never {@code null} */ @Override public final File getFile() { return this.directory; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DirectorySource that = (DirectorySource) o; return this.directory.equals(that.directory); } @Override public int hashCode() { return this.directory.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("directory", this.directory).toString(); } } EngineDescriptor.java000066400000000000000000000031361455764576500370370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.UniqueId; /** * An {@code EngineDescriptor} is a {@link org.junit.platform.engine.TestDescriptor * TestDescriptor} for a specific {@link org.junit.platform.engine.TestEngine TestEngine}. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class EngineDescriptor extends AbstractTestDescriptor { /** * Create a new {@code EngineDescriptor} with the supplied {@link UniqueId} * and display name. * * @param uniqueId the {@code UniqueId} for the described {@code TestEngine}; * never {@code null} * @param displayName the display name for the described {@code TestEngine}; * never {@code null} or blank * @see org.junit.platform.engine.TestEngine#getId() * @see org.junit.platform.engine.TestDescriptor#getDisplayName() */ public EngineDescriptor(UniqueId uniqueId, String displayName) { super(uniqueId, displayName); } /** * Returns {@link org.junit.platform.engine.TestDescriptor.Type#CONTAINER}. * * @see org.junit.platform.engine.TestDescriptor#isContainer() * @see org.junit.platform.engine.TestDescriptor#isTest() */ @Override public Type getType() { return Type.CONTAINER; } } FilePosition.java000066400000000000000000000114631455764576500362010ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serializable; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.ToStringBuilder; /** * Position inside a file represented by {@linkplain #getLine line} and * {@linkplain #getColumn column} numbers. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public class FilePosition implements Serializable { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(FilePosition.class); /** * Create a new {@code FilePosition} using the supplied {@code line} number * and an undefined column number. * * @param line the line number; must be greater than zero * @return a {@link FilePosition} with the given line number */ public static FilePosition from(int line) { return new FilePosition(line); } /** * Create a new {@code FilePosition} using the supplied {@code line} and * {@code column} numbers. * * @param line the line number; must be greater than zero * @param column the column number; must be greater than zero * @return a {@link FilePosition} with the given line and column numbers */ public static FilePosition from(int line, int column) { return new FilePosition(line, column); } /** * Create an optional {@code FilePosition} by parsing the supplied * {@code query} string. * *

Examples of valid {@code query} strings: *

    *
  • {@code "line=23"}
  • *
  • {@code "line=23&column=42"}
  • *
* * @param query the query string; may be {@code null} * @return an {@link Optional} containing a {@link FilePosition} with * the parsed line and column numbers; never {@code null} but potentially * empty * @since 1.3 * @see #from(int) * @see #from(int, int) */ public static Optional fromQuery(String query) { FilePosition result = null; Integer line = null; Integer column = null; if (StringUtils.isNotBlank(query)) { try { for (String pair : query.split("&")) { String[] data = pair.split("="); if (data.length == 2) { String key = data[0]; if (line == null && "line".equals(key)) { line = Integer.valueOf(data[1]); } else if (column == null && "column".equals(key)) { column = Integer.valueOf(data[1]); } } // Already found what we're looking for? if (line != null && column != null) { break; } } } catch (IllegalArgumentException ex) { logger.debug(ex, () -> "Failed to parse 'line' and/or 'column' from query string: " + query); // fall-through and continue } if (line != null) { result = column == null ? new FilePosition(line) : new FilePosition(line, column); } } return Optional.ofNullable(result); } private final int line; private final Integer column; private FilePosition(int line) { Preconditions.condition(line > 0, "line number must be greater than zero"); this.line = line; this.column = null; } private FilePosition(int line, int column) { Preconditions.condition(line > 0, "line number must be greater than zero"); Preconditions.condition(column > 0, "column number must be greater than zero"); this.line = line; this.column = column; } /** * Get the line number of this {@code FilePosition}. * * @return the line number */ public int getLine() { return this.line; } /** * Get the column number of this {@code FilePosition}, if available. * * @return an {@code Optional} containing the column number; never * {@code null} but potentially empty */ public Optional getColumn() { return Optional.ofNullable(this.column); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FilePosition that = (FilePosition) o; return (this.line == that.line) && Objects.equals(this.column, that.column); } @Override public int hashCode() { return Objects.hash(this.line, this.column); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("line", this.line) .append("column", getColumn().orElse(-1)) .toString(); // @formatter:on } } FileSource.java000066400000000000000000000063341455764576500356360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.Objects; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; /** * File based {@link org.junit.platform.engine.TestSource} with an optional * {@linkplain FilePosition position}. * * @since 1.0 * @see org.junit.platform.engine.discovery.FileSelector */ @API(status = STABLE, since = "1.0") public class FileSource implements FileSystemSource { private static final long serialVersionUID = 1L; /** * Create a new {@code FileSource} using the supplied {@link File file}. * * @param file the source file; must not be {@code null} */ public static FileSource from(File file) { return new FileSource(file); } /** * Create a new {@code FileSource} using the supplied {@link File file} and * {@link FilePosition filePosition}. * * @param file the source file; must not be {@code null} * @param filePosition the position in the source file; may be {@code null} */ public static FileSource from(File file, FilePosition filePosition) { return new FileSource(file, filePosition); } private final File file; private final FilePosition filePosition; private FileSource(File file) { this(file, null); } private FileSource(File file, FilePosition filePosition) { Preconditions.notNull(file, "file must not be null"); try { this.file = file.getCanonicalFile(); } catch (IOException ex) { throw new JUnitException("Failed to retrieve canonical path for file: " + file, ex); } this.filePosition = filePosition; } /** * Get the {@link URI} for the source {@linkplain #getFile file}. * * @return the source {@code URI}; never {@code null} */ @Override public final URI getUri() { return getFile().toURI(); } /** * Get the source {@linkplain File file}. * * @return the source file; never {@code null} */ @Override public final File getFile() { return this.file; } /** * Get the {@link FilePosition}, if available. */ public final Optional getPosition() { return Optional.ofNullable(this.filePosition); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FileSource that = (FileSource) o; return Objects.equals(this.file, that.file) && Objects.equals(this.filePosition, that.filePosition); } @Override public int hashCode() { return Objects.hash(this.file, this.filePosition); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("file", this.file) .append("filePosition", this.filePosition) .toString(); // @formatter:on } } FileSystemSource.java000066400000000000000000000017061455764576500370410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; import org.apiguardian.api.API; import org.junit.platform.engine.TestSource; /** * File system based {@link TestSource}. * *

This interface uses {@link File} instead of {@link java.nio.file.Path} * because the latter does not implement {@link java.io.Serializable}. * * @since 1.0 */ @API(status = STABLE, since = "1.0") public interface FileSystemSource extends UriSource { /** * Get the source file or directory. * * @return the source file or directory; never {@code null} */ File getFile(); } MethodSource.java000066400000000000000000000202201455764576500361650ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.ClassUtils.nullSafeToString; import java.lang.reflect.Method; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestSource; /** * Method based {@link org.junit.platform.engine.TestSource TestSource}. * *

This class stores the method name along with the names of its parameter * types because {@link Method} does not implement {@link java.io.Serializable}. * * @since 1.0 * @see org.junit.platform.engine.discovery.MethodSelector */ @API(status = STABLE, since = "1.0") public class MethodSource implements TestSource { private static final long serialVersionUID = 1L; /** * Create a new {@code MethodSource} using the supplied class name and * method name. * * @param className the class name; must not be {@code null} or blank * @param methodName the method name; must not be {@code null} or blank */ public static MethodSource from(String className, String methodName) { return new MethodSource(className, methodName); } /** * Create a new {@code MethodSource} using the supplied class name, method * name, and method parameter types. * * @param className the class name; must not be {@code null} or blank * @param methodName the method name; must not be {@code null} or blank * @param methodParameterTypes a comma-separated list of fully qualified * class names representing the method parameter types */ public static MethodSource from(String className, String methodName, String methodParameterTypes) { return new MethodSource(className, methodName, methodParameterTypes); } /** * Create a new {@code MethodSource} using the supplied class name, method * name, and method parameter types. * * @param className the class name; must not be {@code null} or blank * @param methodName the method name; must not be {@code null} or blank * @param methodParameterTypes a varargs array of classes representing the * method parameter types * @since 1.5 */ @API(status = STABLE, since = "1.5") public static MethodSource from(String className, String methodName, Class... methodParameterTypes) { return new MethodSource(className, methodName, nullSafeToString(methodParameterTypes)); } /** * Create a new {@code MethodSource} using the supplied {@link Method method}. * * @param testMethod the Java method; must not be {@code null} * @see #from(Class, Method) */ public static MethodSource from(Method testMethod) { return new MethodSource(testMethod); } /** * Create a new {@code MethodSource} using the supplied * {@link Class class} and {@link Method method}. * *

This method should be used in favor of {@link #from(Method)} if the * test method is inherited from a superclass or present as an interface * {@code default} method. * * @param testClass the Java class; must not be {@code null} * @param testMethod the Java method; must not be {@code null} * @since 1.3 */ @API(status = STABLE, since = "1.3") public static MethodSource from(Class testClass, Method testMethod) { return new MethodSource(testClass, testMethod); } private final String className; private final String methodName; private final String methodParameterTypes; private Class javaClass; private transient Method javaMethod; private MethodSource(String className, String methodName) { this(className, methodName, null); } private MethodSource(String className, String methodName, String methodParameterTypes) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); this.className = className; this.methodName = methodName; this.methodParameterTypes = methodParameterTypes; } private MethodSource(Method testMethod) { this(Preconditions.notNull(testMethod, "Method must not be null").getDeclaringClass(), testMethod); } /** * @since 1.3 */ private MethodSource(Class testClass, Method testMethod) { Preconditions.notNull(testClass, "Class must not be null"); Preconditions.notNull(testMethod, "Method must not be null"); this.className = testClass.getName(); this.methodName = testMethod.getName(); this.methodParameterTypes = nullSafeToString(testMethod.getParameterTypes()); this.javaClass = testClass; this.javaMethod = testMethod; } /** * Get the class name of this source. */ public String getClassName() { return this.className; } /** * Get the method name of this source. */ public final String getMethodName() { return this.methodName; } /** * Get the method parameter types of this source. */ public final String getMethodParameterTypes() { return this.methodParameterTypes; } /** * Get the {@linkplain Class Java class} of this source. * *

If the {@link Class} was not provided, but only the name, this method * attempts to lazily load the {@link Class} based on its name and throws a * {@link PreconditionViolationException} if the class cannot be loaded. * * @since 1.7 * @see #getClassName() */ @API(status = STABLE, since = "1.7") public final Class getJavaClass() { lazyLoadJavaClass(); return this.javaClass; } /** * Get the {@linkplain Method Java method} of this source. * *

If the {@link Method} was not provided, but only the name, this method * attempts to lazily load the {@code Method} based on its name and throws a * {@link PreconditionViolationException} if the method cannot be loaded. * * @since 1.7 * @see #getMethodName() */ @API(status = STABLE, since = "1.7") public final Method getJavaMethod() { lazyLoadJavaMethod(); return this.javaMethod; } private void lazyLoadJavaClass() { if (this.javaClass == null) { // @formatter:off this.javaClass = ReflectionUtils.tryToLoadClass(this.className).getOrThrow( cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } } private void lazyLoadJavaMethod() { lazyLoadJavaClass(); if (this.javaMethod == null) { if (StringUtils.isNotBlank(this.methodParameterTypes)) { this.javaMethod = ReflectionUtils.findMethod(this.javaClass, this.methodName, this.methodParameterTypes).orElseThrow( () -> new PreconditionViolationException(String.format( "Could not find method with name [%s] and parameter types [%s] in class [%s].", this.methodName, this.methodParameterTypes, this.javaClass.getName()))); } else { this.javaMethod = ReflectionUtils.findMethod(this.javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( String.format("Could not find method with name [%s] in class [%s].", this.methodName, this.javaClass.getName()))); } } } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MethodSource that = (MethodSource) o; return Objects.equals(this.className, that.className)// && Objects.equals(this.methodName, that.methodName)// && Objects.equals(this.methodParameterTypes, that.methodParameterTypes); } @Override public int hashCode() { return Objects.hash(this.className, this.methodName, this.methodParameterTypes); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("className", this.className) .append("methodName", this.methodName) .append("methodParameterTypes", this.methodParameterTypes) .toString(); // @formatter:on } } PackageSource.java000066400000000000000000000046761455764576500363210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestSource; /** * Package based {@link org.junit.platform.engine.TestSource}. * *

This class stores the package name because {@link Package} does not * implement {@link java.io.Serializable}. * * @since 1.0 * @see org.junit.platform.engine.discovery.PackageSelector */ @API(status = STABLE, since = "1.0") public class PackageSource implements TestSource { private static final long serialVersionUID = 1L; /** * Create a new {@code PackageSource} using the supplied Java {@link Package}. * * @param javaPackage the Java package; must not be {@code null} */ public static PackageSource from(Package javaPackage) { return new PackageSource(javaPackage); } /** * Create a new {@code PackageSource} using the supplied {@code packageName}. * * @param packageName the package name; must not be {@code null} or blank */ public static PackageSource from(String packageName) { return new PackageSource(packageName); } private final String packageName; private PackageSource(Package javaPackage) { this(Preconditions.notNull(javaPackage, "package must not be null").getName()); } private PackageSource(String packageName) { this.packageName = Preconditions.notBlank(packageName, "package name must not be null or blank"); } /** * Get the package name of this test source. */ public final String getPackageName() { return this.packageName; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PackageSource that = (PackageSource) o; return Objects.equals(this.packageName, that.packageName); } @Override public int hashCode() { return this.packageName.hashCode(); } @Override public String toString() { return new ToStringBuilder(this).append("packageName", this.packageName).toString(); } } ResourceUtils.java000066400000000000000000000023611455764576500364020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import java.net.URI; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; /** * Collection of static utility methods for working with resources. * * @since 1.3 */ final class ResourceUtils { private ResourceUtils() { /* no-op */ } /** * Strip the {@link URI#getQuery() query} component from the supplied * {@link URI}. * * @param uri the {@code URI} from which to strip the query component * @return a new {@code URI} with the query component removed, or the * original {@code URI} unmodified if it does not have a query component */ static URI stripQueryComponent(URI uri) { Preconditions.notNull(uri, "URI must not be null"); if (StringUtils.isBlank(uri.getQuery())) { return uri; } String uriAsString = uri.toString(); return URI.create(uriAsString.substring(0, uriAsString.indexOf('?'))); } } UriSource.java000066400000000000000000000046751455764576500355240ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.apiguardian.api.API.Status.STABLE; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apiguardian.api.API; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestSource; /** * A {@link TestSource} that can be represented as a {@link URI}. * * @since 1.0 * @see org.junit.platform.engine.discovery.UriSelector */ @API(status = STABLE, since = "1.0") public interface UriSource extends TestSource { /** * Get the {@link URI} that represents this source. * * @return the source {@code URI}; never {@code null} */ URI getUri(); /** * Create a new {@code UriSource} using the supplied {@code URI}. * *

This implementation first attempts to resolve the supplied {@code URI} * to a path-based {@code UriSource} in the local filesystem. If that fails * for any reason, an instance of the default {@code UriSource} * implementation storing the supplied {@code URI} as-is will be * returned. * * @param uri the URI to use as the source; never {@code null} * @return an appropriate {@code UriSource} for the supplied {@code URI} * @since 1.3 * @see org.junit.platform.engine.support.descriptor.FileSource * @see org.junit.platform.engine.support.descriptor.DirectorySource */ static UriSource from(URI uri) { Preconditions.notNull(uri, "URI must not be null"); try { URI uriWithoutQuery = ResourceUtils.stripQueryComponent(uri); Path path = Paths.get(uriWithoutQuery); if (Files.isRegularFile(path)) { return FileSource.from(path.toFile(), FilePosition.fromQuery(uri.getQuery()).orElse(null)); } if (Files.isDirectory(path)) { return DirectorySource.from(path.toFile()); } } catch (RuntimeException ex) { LoggerFactory.getLogger(UriSource.class).debug(ex, () -> String.format( "The supplied URI [%s] is not path-based. Falling back to default UriSource implementation.", uri)); } // Store supplied URI as-is return new DefaultUriSource(uri); } } package-info.java000066400000000000000000000003411455764576500361120ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/** * {@link org.junit.platform.engine.TestDescriptor}-related support classes * intended to be used by test engine implementations and clients of * the launcher. */ package org.junit.platform.engine.support.descriptor; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/000077500000000000000000000000001455764576500326355ustar00rootroot00000000000000ClassContainerSelectorResolver.java000066400000000000000000000045171455764576500415630ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.discovery; import static java.util.stream.Collectors.toSet; import static org.junit.platform.commons.support.ReflectionSupport.findAllClassesInClasspathRoot; import static org.junit.platform.commons.support.ReflectionSupport.findAllClassesInModule; import static org.junit.platform.commons.support.ReflectionSupport.findAllClassesInPackage; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.selectors; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import java.util.List; import java.util.function.Predicate; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; /** * @since 1.5 */ class ClassContainerSelectorResolver implements SelectorResolver { private final Predicate> classFilter; private final Predicate classNameFilter; ClassContainerSelectorResolver(Predicate> classFilter, Predicate classNameFilter) { this.classFilter = classFilter; this.classNameFilter = classNameFilter; } @Override public Resolution resolve(ClasspathRootSelector selector, Context context) { return classSelectors(findAllClassesInClasspathRoot(selector.getClasspathRoot(), classFilter, classNameFilter)); } @Override public Resolution resolve(ModuleSelector selector, Context context) { return classSelectors(findAllClassesInModule(selector.getModuleName(), classFilter, classNameFilter)); } @Override public Resolution resolve(PackageSelector selector, Context context) { return classSelectors(findAllClassesInPackage(selector.getPackageName(), classFilter, classNameFilter)); } private Resolution classSelectors(List> classes) { if (classes.isEmpty()) { return unresolved(); } return selectors(classes.stream().map(DiscoverySelectors::selectClass).collect(toSet())); } } EngineDiscoveryRequestResolution.java000066400000000000000000000233271455764576500421620ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.discovery; import static java.util.stream.Collectors.joining; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.SelectorResolutionResult.failed; import static org.junit.platform.engine.SelectorResolutionResult.resolved; import static org.junit.platform.engine.SelectorResolutionResult.unresolved; import java.util.ArrayDeque; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Queue; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryListener; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.NestedClassSelector; import org.junit.platform.engine.discovery.NestedMethodSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.discovery.UriSelector; import org.junit.platform.engine.support.discovery.SelectorResolver.Context; import org.junit.platform.engine.support.discovery.SelectorResolver.Match; import org.junit.platform.engine.support.discovery.SelectorResolver.Resolution; /** * @since 1.5 */ class EngineDiscoveryRequestResolution { private final EngineDiscoveryRequest request; private final Context defaultContext; private final List resolvers; private final List visitors; private final TestDescriptor engineDescriptor; private final Map resolvedSelectors = new LinkedHashMap<>(); private final Map resolvedUniqueIds = new LinkedHashMap<>(); private final Queue remainingSelectors = new ArrayDeque<>(); private final Map contextBySelector = new HashMap<>(); EngineDiscoveryRequestResolution(EngineDiscoveryRequest request, TestDescriptor engineDescriptor, List resolvers, List visitors) { this.request = request; this.engineDescriptor = engineDescriptor; this.resolvers = resolvers; this.visitors = visitors; this.defaultContext = new DefaultContext(null); this.resolvedUniqueIds.put(engineDescriptor.getUniqueId(), Match.exact(engineDescriptor)); } void run() { remainingSelectors.addAll(request.getSelectorsByType(DiscoverySelector.class)); while (!remainingSelectors.isEmpty()) { resolveCompletely(remainingSelectors.poll()); } visitors.forEach(engineDescriptor::accept); } private void resolveCompletely(DiscoverySelector selector) { EngineDiscoveryListener discoveryListener = request.getDiscoveryListener(); UniqueId engineId = engineDescriptor.getUniqueId(); try { Optional result = resolve(selector); if (result.isPresent()) { discoveryListener.selectorProcessed(engineId, selector, resolved()); enqueueAdditionalSelectors(result.get()); } else { discoveryListener.selectorProcessed(engineId, selector, unresolved()); } } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); discoveryListener.selectorProcessed(engineId, selector, failed(t)); } } private void enqueueAdditionalSelectors(Resolution resolution) { remainingSelectors.addAll(resolution.getSelectors()); resolution.getMatches().stream().filter(Match::isExact).forEach(match -> { Set childSelectors = match.expand(); if (!childSelectors.isEmpty()) { remainingSelectors.addAll(childSelectors); DefaultContext context = new DefaultContext(match.getTestDescriptor()); childSelectors.forEach(selector -> contextBySelector.put(selector, context)); } }); } private Optional resolve(DiscoverySelector selector) { if (resolvedSelectors.containsKey(selector)) { return Optional.of(resolvedSelectors.get(selector)); } if (selector instanceof UniqueIdSelector) { return resolveUniqueId((UniqueIdSelector) selector); } return resolve(selector, resolver -> { Context context = getContext(selector); if (selector instanceof ClasspathResourceSelector) { return resolver.resolve((ClasspathResourceSelector) selector, context); } if (selector instanceof ClasspathRootSelector) { return resolver.resolve((ClasspathRootSelector) selector, context); } if (selector instanceof ClassSelector) { return resolver.resolve((ClassSelector) selector, context); } if (selector instanceof IterationSelector) { return resolver.resolve((IterationSelector) selector, context); } if (selector instanceof NestedClassSelector) { return resolver.resolve((NestedClassSelector) selector, context); } if (selector instanceof DirectorySelector) { return resolver.resolve((DirectorySelector) selector, context); } if (selector instanceof FileSelector) { return resolver.resolve((FileSelector) selector, context); } if (selector instanceof MethodSelector) { return resolver.resolve((MethodSelector) selector, context); } if (selector instanceof NestedMethodSelector) { return resolver.resolve((NestedMethodSelector) selector, context); } if (selector instanceof ModuleSelector) { return resolver.resolve((ModuleSelector) selector, context); } if (selector instanceof PackageSelector) { return resolver.resolve((PackageSelector) selector, context); } if (selector instanceof UriSelector) { return resolver.resolve((UriSelector) selector, context); } return resolver.resolve(selector, context); }); } private Optional resolveUniqueId(UniqueIdSelector selector) { UniqueId uniqueId = selector.getUniqueId(); if (resolvedUniqueIds.containsKey(uniqueId)) { return Optional.of(Resolution.match(resolvedUniqueIds.get(uniqueId))); } if (!uniqueId.hasPrefix(engineDescriptor.getUniqueId())) { return Optional.empty(); } return resolve(selector, resolver -> resolver.resolve(selector, getContext(selector))); } private Context getContext(DiscoverySelector selector) { return contextBySelector.getOrDefault(selector, defaultContext); } private Optional resolve(DiscoverySelector selector, Function resolutionFunction) { // @formatter:off return resolvers.stream() .map(resolutionFunction) .filter(Resolution::isResolved) .findFirst() .map(resolution -> { contextBySelector.remove(selector); resolvedSelectors.put(selector, resolution); resolution.getMatches() .forEach(match -> resolvedUniqueIds.put(match.getTestDescriptor().getUniqueId(), match)); return resolution; }); // @formatter:on } private class DefaultContext implements Context { private final TestDescriptor parent; DefaultContext(TestDescriptor parent) { this.parent = parent; } @Override public Optional addToParent(Function> creator) { if (parent != null) { return createAndAdd(parent, creator); } return createAndAdd(engineDescriptor, creator); } @Override public Optional addToParent(Supplier parentSelectorSupplier, Function> creator) { if (parent != null) { return createAndAdd(parent, creator); } return resolve(parentSelectorSupplier.get()).flatMap(parent -> createAndAdd(parent, creator)); } @Override public Optional resolve(DiscoverySelector selector) { // @formatter:off return EngineDiscoveryRequestResolution.this.resolve(selector) .map(Resolution::getMatches) .flatMap(matches -> { if (matches.size() > 1) { String stringRepresentation = matches.stream() .map(Match::getTestDescriptor) .map(Objects::toString) .collect(joining(", ")); throw new JUnitException( "Selector " + selector + " did not yield unique test descriptor: " + stringRepresentation); } if (matches.size() == 1) { return Optional.of(getOnlyElement(matches).getTestDescriptor()); } return Optional.empty(); }); // @formatter:on } @SuppressWarnings("unchecked") private Optional createAndAdd(TestDescriptor parent, Function> creator) { Optional child = creator.apply(parent); if (child.isPresent()) { UniqueId uniqueId = child.get().getUniqueId(); if (resolvedUniqueIds.containsKey(uniqueId)) { return Optional.of((T) resolvedUniqueIds.get(uniqueId).getTestDescriptor()); } parent.addChild(child.get()); } return child; } } } EngineDiscoveryRequestResolver.java000066400000000000000000000255341455764576500416220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.discovery; import static java.util.stream.Collectors.toCollection; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.Filter; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.support.discovery.SelectorResolver.Match; import org.junit.platform.engine.support.discovery.SelectorResolver.Resolution; /** * Configurable test discovery implementation based on {@link SelectorResolver} * and {@link TestDescriptor.Visitor} that can be reused by different * {@link org.junit.platform.engine.TestEngine TestEngines}. * *

This resolver takes care of notifying registered * {@link org.junit.platform.engine.EngineDiscoveryListener * EngineDiscoveryListeners} about the results of processed * {@link org.junit.platform.engine.DiscoverySelector DiscoverySelectors}. * * @param the type of the engine's descriptor * @since 1.5 * @see #builder() * @see #resolve(EngineDiscoveryRequest, TestDescriptor) */ @API(status = STABLE, since = "1.10") public class EngineDiscoveryRequestResolver { private final List, SelectorResolver>> resolverCreators; private final List, TestDescriptor.Visitor>> visitorCreators; private EngineDiscoveryRequestResolver(List, SelectorResolver>> resolverCreators, List, TestDescriptor.Visitor>> visitorCreators) { this.resolverCreators = new ArrayList<>(resolverCreators); this.visitorCreators = new ArrayList<>(visitorCreators); } /** * Resolve the supplied {@link EngineDiscoveryRequest} and collect the * results into the supplied {@link TestDescriptor}. * *

The algorithm works as follows: * *

    *
  1. Enqueue all selectors in the supplied * {@linkplain EngineDiscoveryRequest request} to be resolved. *
  2. *
  3. * While there are selectors to be resolved, get the next one. * Otherwise, the resolution is finished. *
      *
    1. * Iterate over all registered {@linkplain SelectorResolver * resolvers} in the order they were registered in and find the * first one that returns a {@linkplain Resolution resolution} * other than {@link Resolution#unresolved() unresolved()}. *
    2. *
    3. * If such a {@linkplain Resolution resolution} exists, enqueue * its {@linkplain Resolution#getSelectors() selectors}. *
    4. *
    5. * For each exact {@linkplain Match match} in the {@linkplain * Resolution resolution}, {@linkplain Match#expand() expand} * its children and enqueue them as well. *
    6. *
    *
  4. *
  5. * Iterate over all registered {@linkplain TestDescriptor.Visitor * visitors} and let the engine test descriptor {@linkplain * TestDescriptor#accept(TestDescriptor.Visitor) accept} them. *
  6. *
* * @param request the request to be resolved; never {@code null} * @param engineDescriptor the engine's {@code TestDescriptor} to be used * for adding direct children * @see SelectorResolver * @see TestDescriptor.Visitor */ public void resolve(EngineDiscoveryRequest request, T engineDescriptor) { Preconditions.notNull(request, "request must not be null"); Preconditions.notNull(engineDescriptor, "engineDescriptor must not be null"); InitializationContext initializationContext = new DefaultInitializationContext<>(request, engineDescriptor); List resolvers = instantiate(resolverCreators, initializationContext); List visitors = instantiate(visitorCreators, initializationContext); new EngineDiscoveryRequestResolution(request, engineDescriptor, resolvers, visitors).run(); } private List instantiate(List, R>> creators, InitializationContext context) { return creators.stream().map(creator -> creator.apply(context)).collect(toCollection(ArrayList::new)); } /** * Create a new {@link Builder} for creating a {@link EngineDiscoveryRequestResolver}. * * @param the type of the engine's descriptor * @return a new builder; never {@code null} */ public static Builder builder() { return new Builder<>(); } /** * Builder for {@link EngineDiscoveryRequestResolver}. * * @param the type of the engine's descriptor * @since 1.5 */ @API(status = STABLE, since = "1.10") public static class Builder { private final List, SelectorResolver>> resolverCreators = new ArrayList<>(); private final List, TestDescriptor.Visitor>> visitorCreators = new ArrayList<>(); private Builder() { } /** * Add a predefined resolver that resolves {@link ClasspathRootSelector * ClasspathRootSelectors}, {@link ModuleSelector ModuleSelectors}, and * {@link PackageSelector PackageSelectors} into {@link ClassSelector * ClassSelectors} by scanning for classes that satisfy the supplied * predicate in the respective class containers to this builder. * * @param classFilter predicate the resolved classes must satisfy; never * {@code null} * @return this builder for method chaining */ public Builder addClassContainerSelectorResolver(Predicate> classFilter) { Preconditions.notNull(classFilter, "classFilter must not be null"); return addSelectorResolver( context -> new ClassContainerSelectorResolver(classFilter, context.getClassNameFilter())); } /** * Add a context insensitive {@link SelectorResolver} to this builder. * * @param resolver the resolver to add; never {@code null} * @return this builder for method chaining */ public Builder addSelectorResolver(SelectorResolver resolver) { Preconditions.notNull(resolver, "resolver must not be null"); return addSelectorResolver(context -> resolver); } /** * Add a context sensitive {@link SelectorResolver} to this builder. * * @param resolverCreator the function that will be called to create the * {@link SelectorResolver} to be added. * @return this builder for method chaining * @see InitializationContext */ public Builder addSelectorResolver(Function, SelectorResolver> resolverCreator) { resolverCreators.add(resolverCreator); return this; } /** * Add a context sensitive {@link TestDescriptor.Visitor} to this * builder. * * @param visitorCreator the function that will be called to create the * {@link TestDescriptor.Visitor} to be added. * @return this builder for method chaining * @see InitializationContext */ public Builder addTestDescriptorVisitor( Function, TestDescriptor.Visitor> visitorCreator) { visitorCreators.add(visitorCreator); return this; } /** * Build the {@link EngineDiscoveryRequestResolver} that has been * configured via this builder. */ public EngineDiscoveryRequestResolver build() { return new EngineDiscoveryRequestResolver<>(resolverCreators, visitorCreators); } } /** * The initialization context for creating {@linkplain SelectorResolver * resolvers} and {@linkplain TestDescriptor.Visitor visitors} that depend * on the {@link EngineDiscoveryRequest} to be resolved or the engine * descriptor that will be used to collect the results. * * @since 1.5 * @see Builder#addSelectorResolver(Function) * @see Builder#addTestDescriptorVisitor(Function) */ @API(status = STABLE, since = "1.10") public interface InitializationContext { /** * Get the {@link EngineDiscoveryRequest} that is about to be resolved. * * @return the {@link EngineDiscoveryRequest}; never {@code null} */ EngineDiscoveryRequest getDiscoveryRequest(); /** * Get the engine's {@link TestDescriptor} that will be used to collect * the results. * * @return engine's {@link TestDescriptor}; never {@code null} */ T getEngineDescriptor(); /** * Get the class name filter built from the {@link ClassNameFilter * ClassNameFilters} and {@link PackageNameFilter PackageNameFilters} * in the {@link EngineDiscoveryRequest} that is about to be resolved. * * @return the predicate for filtering the resolved class names; never * {@code null} */ Predicate getClassNameFilter(); } private static class DefaultInitializationContext implements InitializationContext { private final EngineDiscoveryRequest request; private final T engineDescriptor; private final Predicate classNameFilter; DefaultInitializationContext(EngineDiscoveryRequest request, T engineDescriptor) { this.request = request; this.engineDescriptor = engineDescriptor; this.classNameFilter = buildClassNamePredicate(request); } /** * Build a {@link Predicate} for fully qualified class names to be used for * classpath scanning from an {@link EngineDiscoveryRequest}. * * @param request the request to build a predicate from */ private Predicate buildClassNamePredicate(EngineDiscoveryRequest request) { List> filters = new ArrayList<>(); filters.addAll(request.getFiltersByType(ClassNameFilter.class)); filters.addAll(request.getFiltersByType(PackageNameFilter.class)); return Filter.composeFilters(filters).toPredicate(); } @Override public EngineDiscoveryRequest getDiscoveryRequest() { return request; } @Override public T getEngineDescriptor() { return engineDescriptor; } @Override public Predicate getClassNameFilter() { return classNameFilter; } } } SelectorResolver.java000066400000000000000000000633721455764576500367360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.discovery; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.NestedClassSelector; import org.junit.platform.engine.discovery.NestedMethodSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.discovery.UriSelector; /** * A resolver that supports resolving one or multiple types of * {@link DiscoverySelector DiscoverySelectors}. * *

An implementation of a {@code resolve()} method is typically comprised * of the following steps: * *

    *
  1. * Check whether the selector is applicable for the current * {@link org.junit.platform.engine.TestEngine} and the current * {@link org.junit.platform.engine.EngineDiscoveryRequest} (e.g. * for a test class: is it relevant for the current engine and does * it pass all filters in the request?). *
  2. *
  3. * If so, use the supplied {@link Context Context}, to add one or * multiple {@link TestDescriptor TestDescriptors} to the designated * parent (see {@link Context Context} for details) and return a * {@linkplain Resolution#match(Match) match} or multiple {@linkplain * Resolution#matches(Set) matches}. Alternatively, convert the supplied * selector into one or multiple other * {@linkplain Resolution#selectors(Set) selectors} (e.g. a {@link * PackageSelector} into a set of {@link ClassSelector ClassSelectors}). * Otherwise, return {@link Resolution#unresolved() unresolved()}. *
  4. *
* * @since 1.5 */ @API(status = STABLE, since = "1.10") public interface SelectorResolver { /** * Resolve the supplied {@link ClasspathResourceSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(ClasspathResourceSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link ClasspathRootSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(ClasspathRootSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link ClassSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(ClassSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link NestedClassSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(NestedClassSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link DirectorySelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(DirectorySelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link FileSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(FileSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link MethodSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(MethodSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link NestedMethodSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(NestedMethodSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link ModuleSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(ModuleSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link PackageSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(PackageSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link UniqueIdSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(UniqueIdSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link UriSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ default Resolution resolve(UriSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link IterationSelector} using the supplied * {@link Context Context}. * *

The default implementation delegates to {@link * #resolve(DiscoverySelector, Context)}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ @API(status = EXPERIMENTAL, since = "1.9") default Resolution resolve(IterationSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } /** * Resolve the supplied {@link DiscoverySelector} using the supplied * {@link Context Context}. * *

This method is only called if none of the overloaded variants match. * *

The default implementation returns {@link Resolution#unresolved() * unresolved()}. * * @param selector the selector to be resolved; never {@code null} * @param context the context to be used for resolving the selector; never * {@code null} * @return a {@link Resolution Resolution} of {@link Resolution#unresolved() * unresolved()}, {@link Resolution#selectors(Set) selectors()}, or {@link * Resolution#matches(Set) matches()}; never {@code null} * @see Context */ default Resolution resolve(DiscoverySelector selector, Context context) { return Resolution.unresolved(); } /** * The context for resolving a {@link DiscoverySelector} and adding it to * the test tree. * *

The context is used to add resolved {@link TestDescriptor * TestDescriptors} to the test tree if and only if the parent * {@code TestDescriptor} could be found. Alternatively, a resolver may * use the context to {@linkplain #resolve(DiscoverySelector) resolve} a * certain {@code DiscoverySelector} into a {@code TestDescriptor} (e.g. for * adding a filter and returning a {@linkplain Match#partial(TestDescriptor) * partial match}). * * @since 1.5 * @see SelectorResolver */ @API(status = STABLE, since = "1.10") interface Context { /** * Resolve the supplied {@link TestDescriptor}, if possible. * *

Calling this method has the same effect as returning a {@linkplain * Match#partial(TestDescriptor) partial match} from a {@link * SelectorResolver}: the children of the resulting {@link * TestDescriptor} will only be resolved if a subsequent resolution * finds an exact match that contains a {@code TestDescriptor} with the * same {@linkplain TestDescriptor#getUniqueId() unique ID}. * * @param selector the selector to resolve * @return the resolved {@code TestDescriptor}; never {@code null} but * potentially empty */ Optional resolve(DiscoverySelector selector); /** * Add a {@link TestDescriptor} to an unspecified parent, usually the * engine descriptor, by applying the supplied {@code Function} to the * new parent. * *

The parent will be the engine descriptor unless another parent has * already been determined, i.e. if the selector that is being resolved * is the result of {@linkplain Match#expand() expanding} a {@link * Match}. * *

If the result of applying the {@code Function} is {@linkplain * Optional#isPresent() present}, it will be added as a child of the * parent {@code TestDescriptor} unless a descriptor with the same * {@linkplain TestDescriptor#getUniqueId() unique ID} was added * earlier. * * @param creator {@code Function} that will be called with the new * parent to determine the new {@code TestDescriptor} to be added; must * not return {@code null} * @param the type of the new {@code TestDescriptor} * @return the new {@code TestDescriptor} or the previously existing one * with the same unique ID; never {@code null} but potentially empty * @throws ClassCastException if the previously existing {@code * TestDescriptor} is not an instance of {@code T} */ Optional addToParent(Function> creator); /** * Add a {@link TestDescriptor} to a parent, specified by the {@link * DiscoverySelector} returned by the supplied {@code Supplier}, by * applying the supplied {@code Function} to the new parent. * *

Unless another parent has already been determined, i.e. if the * selector that is being resolved is the result of {@linkplain * Match#expand() expanding} a {@link Match}, the {@link * DiscoverySelector} returned by the supplied {@code Supplier} will * be used to determine the parent. If no parent is found, the supplied * {@code Function} will not be called. If there are multiple potential * parents, an exception will be thrown. Otherwise, the resolved * {@code TestDescriptor} will be used as the parent and passed to the * supplied {@code Function}. * *

If the result of applying the {@code Function} is {@linkplain * Optional#isPresent() present}, it will be added as a child of the * parent {@code TestDescriptor} unless a descriptor with the same * {@linkplain TestDescriptor#getUniqueId() unique ID} was added * earlier. * * @param creator {@code Function} that will be called with the new * parent to determine the new {@code TestDescriptor} to be added; must * not return {@code null} * @param the type of the new {@code TestDescriptor} * @return the new {@code TestDescriptor} or the previously existing one * with the same unique ID; never {@code null} but potentially empty * @throws ClassCastException if the previously existing {@code * TestDescriptor} is not an instance of {@code T} */ Optional addToParent(Supplier parentSelectorSupplier, Function> creator); } /** * The result of an attempt to resolve a {@link DiscoverySelector}. * *

A resolution is either {@linkplain #unresolved unresolved}, contains a * {@linkplain #match match} or multiple {@linkplain #matches}, or a set of * {@linkplain #selectors selectors}. * * @since 1.5 * @see SelectorResolver */ @API(status = STABLE, since = "1.10") class Resolution { private static final Resolution UNRESOLVED = new Resolution(emptySet(), emptySet()); private final Set matches; private final Set selectors; /** * Factory for creating unresolved resolutions. * * @return an unresolved resolution; never {@code null} */ public static Resolution unresolved() { return UNRESOLVED; } /** * Factory for creating a resolution that contains the supplied * {@link Match Match}. * * @param match the resolved {@code Match}; never {@code null} * @return an resolution that contains the supplied {@code Match}; never * {@code null} */ public static Resolution match(Match match) { return new Resolution(singleton(match), emptySet()); } /** * Factory for creating a resolution that contains the supplied * {@link Match Matches}. * * @param matches the resolved {@code Matches}; never {@code null} or * empty * @return an resolution that contains the supplied {@code Matches}; * never {@code null} */ public static Resolution matches(Set matches) { Preconditions.containsNoNullElements(matches, "matches must not contain null elements"); Preconditions.notEmpty(matches, "matches must not be empty"); return new Resolution(matches, emptySet()); } /** * Factory for creating a resolution that contains the supplied * {@link DiscoverySelector DiscoverySelectors}. * * @param selectors the resolved {@code DiscoverySelectors}; never * {@code null} or empty * @return an resolution that contains the supplied * {@code DiscoverySelectors}; never {@code null} */ public static Resolution selectors(Set selectors) { Preconditions.containsNoNullElements(selectors, "selectors must not contain null elements"); Preconditions.notEmpty(selectors, "selectors must not be empty"); return new Resolution(emptySet(), selectors); } private Resolution(Set matches, Set selectors) { this.matches = matches; this.selectors = selectors; } /** * Whether this resolution contains matches or selectors. * * @return {@code true} if this resolution contains matches or selectors */ public boolean isResolved() { return this != UNRESOLVED; } /** * Returns the matches contained by this resolution. * * @return the set of matches; never {@code null} but potentially empty */ public Set getMatches() { return matches; } /** * Returns the selectors contained by this resolution. * * @return the set of selectors; never {@code null} but potentially empty */ public Set getSelectors() { return selectors; } } /** * An exact or partial match for resolving a {@link DiscoverySelector} into * a {@link TestDescriptor}. * *

A match is exact if the {@link DiscoverySelector} directly * represents the resulting {@link TestDescriptor}, e.g. if a * {@link ClassSelector} was resolved into the {@link TestDescriptor} that * represents the test class. It is partial if the matching * {@link TestDescriptor} does not directly correspond to the resolved * {@link DiscoverySelector}, e.g. when resolving a {@link UniqueIdSelector} * that represents a dynamic child of the resolved {@link TestDescriptor}. * *

In addition to the {@link TestDescriptor}, a match may contain a * {@code Supplier} of {@link DiscoverySelector DiscoverySelectors} that may * be used to discover the children of the {@link TestDescriptor}. The * algorithm implemented by {@link EngineDiscoveryRequestResolver} * {@linkplain #expand() expands} all exact matches immediately, i.e. it * resolves all of their children. Partial matches will only be expanded in * case a subsequent resolution finds an exact match that contains a {@link * TestDescriptor} with the same {@linkplain TestDescriptor#getUniqueId() * unique ID}. * * @since 1.5 * @see SelectorResolver * @see Resolution#match(Match) * @see Resolution#matches(Set) */ @API(status = STABLE, since = "1.10") class Match { private final TestDescriptor testDescriptor; private final Supplier> childSelectorsSupplier; private final Type type; /** * Factory for creating an exact match without any children. * * @param testDescriptor the resolved {@code TestDescriptor}; never * {@code null} * @return a match that contains the supplied {@code TestDescriptor}; * never {@code null} */ public static Match exact(TestDescriptor testDescriptor) { return exact(testDescriptor, Collections::emptySet); } /** * Factory for creating an exact match with potential children. * * @param testDescriptor the resolved {@code TestDescriptor}; never * {@code null} * @param childSelectorsSupplier a {@code Supplier} of children * selectors that will be resolved when this match is expanded; never * {@code null} * @return a match that contains the supplied {@code TestDescriptor}; * never {@code null} */ public static Match exact(TestDescriptor testDescriptor, Supplier> childSelectorsSupplier) { return new Match(testDescriptor, childSelectorsSupplier, Type.EXACT); } /** * Factory for creating a partial match without any children. * * @param testDescriptor the resolved {@code TestDescriptor}; never * {@code null} * @return a match that contains the supplied {@code TestDescriptor}; * never {@code null} */ public static Match partial(TestDescriptor testDescriptor) { return partial(testDescriptor, Collections::emptySet); } /** * Factory for creating a partial match with potential children. * * @param testDescriptor the resolved {@code TestDescriptor}; never * {@code null} * @param childSelectorsSupplier a {@code Supplier} of children * selectors that will be resolved when this match is expanded; never * {@code null} * @return a match that contains the supplied {@code TestDescriptor}; * never {@code null} */ public static Match partial(TestDescriptor testDescriptor, Supplier> childSelectorsSupplier) { return new Match(testDescriptor, childSelectorsSupplier, Type.PARTIAL); } private Match(TestDescriptor testDescriptor, Supplier> childSelectorsSupplier, Type type) { this.testDescriptor = Preconditions.notNull(testDescriptor, "testDescriptor must not be null"); this.childSelectorsSupplier = Preconditions.notNull(childSelectorsSupplier, "childSelectorsSupplier must not be null"); this.type = type; } /** * Whether this match is exact. * * @return {@code true} if this match is exact; {@code false} if it's * partial */ public boolean isExact() { return type == Type.EXACT; } /** * Get the contained {@link TestDescriptor}. * * @return the contained {@code TestDescriptor}; never {@code null} */ public TestDescriptor getTestDescriptor() { return testDescriptor; } /** * Expand this match in order to resolve the children of the contained * {@link TestDescriptor}. * * @return the set of {@code DiscoverySelectors} that represent the * children of the contained {@code TestDescriptor}; never {@code null} */ public Set expand() { return childSelectorsSupplier.get(); } private enum Type { EXACT, PARTIAL } } } package-info.java000066400000000000000000000006321455764576500357460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/** * Configurable test discovery implementation that can be reused by different test engines. * * @see org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver#builder() * @see org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver#resolve * @see org.junit.platform.engine.support.discovery.SelectorResolver */ package org.junit.platform.engine.support.discovery; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/000077500000000000000000000000001455764576500321135ustar00rootroot00000000000000ClasspathScanningSupport.java000066400000000000000000000050171455764576500377020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.filter; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.junit.platform.engine.Filter.composeFilters; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.ClassFilter; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.PackageNameFilter; /** * Support utility methods for classpath scanning. * * @since 1.0 * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. */ @Deprecated @API(status = DEPRECATED, since = "1.5") public final class ClasspathScanningSupport { private ClasspathScanningSupport() { /* no-op */ } /** * Build a {@link Predicate} for fully qualified class names to be used for * classpath scanning from an {@link EngineDiscoveryRequest}. * * @param request the request to build a predicate from * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. */ @Deprecated public static Predicate buildClassNamePredicate(EngineDiscoveryRequest request) { List> filters = new ArrayList<>(); filters.addAll(request.getFiltersByType(ClassNameFilter.class)); filters.addAll(request.getFiltersByType(PackageNameFilter.class)); return composeFilters(filters).toPredicate(); } /** * Build a {@link ClassFilter} by combining the name predicate built by * {@link #buildClassNamePredicate(EngineDiscoveryRequest)} and the passed-in * class predicate. * * @param request the request to build a name predicate from * @param classPredicate the class predicate * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. */ @Deprecated @SuppressWarnings("exports") public static ClassFilter buildClassFilter(EngineDiscoveryRequest request, Predicate> classPredicate) { return ClassFilter.of(buildClassNamePredicate(request), classPredicate); } } package-info.java000066400000000000000000000002661455764576500352270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/** * {@link org.junit.platform.engine.Filter}-related support classes intended to be * used by test engine implementations. */ package org.junit.platform.engine.support.filter; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/000077500000000000000000000000001455764576500332445ustar00rootroot00000000000000CompositeLock.java000066400000000000000000000032751455764576500366120ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.locks.Lock; /** * @since 1.3 */ class CompositeLock implements ResourceLock { private final List locks; CompositeLock(List locks) { this.locks = locks; } // for tests only List getLocks() { return locks; } @Override public ResourceLock acquire() throws InterruptedException { ForkJoinPool.managedBlock(new CompositeLockManagedBlocker()); return this; } private void acquireAllLocks() throws InterruptedException { List acquiredLocks = new ArrayList<>(locks.size()); try { for (Lock lock : locks) { lock.lockInterruptibly(); acquiredLocks.add(lock); } } catch (InterruptedException e) { release(acquiredLocks); throw e; } } @Override public void release() { release(locks); } private void release(List acquiredLocks) { for (int i = acquiredLocks.size() - 1; i >= 0; i--) { acquiredLocks.get(i).unlock(); } } private class CompositeLockManagedBlocker implements ForkJoinPool.ManagedBlocker { private boolean acquired; @Override public boolean block() throws InterruptedException { acquireAllLocks(); acquired = true; return true; } @Override public boolean isReleasable() { return acquired; } } } DefaultParallelExecutionConfiguration.java000066400000000000000000000031661455764576500435130ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.concurrent.ForkJoinPool; import java.util.function.Predicate; /** * @since 1.3 */ class DefaultParallelExecutionConfiguration implements ParallelExecutionConfiguration { private final int parallelism; private final int minimumRunnable; private final int maxPoolSize; private final int corePoolSize; private final int keepAliveSeconds; private final Predicate saturate; DefaultParallelExecutionConfiguration(int parallelism, int minimumRunnable, int maxPoolSize, int corePoolSize, int keepAliveSeconds, Predicate saturate) { this.parallelism = parallelism; this.minimumRunnable = minimumRunnable; this.maxPoolSize = maxPoolSize; this.corePoolSize = corePoolSize; this.keepAliveSeconds = keepAliveSeconds; this.saturate = saturate; } @Override public int getParallelism() { return parallelism; } @Override public int getMinimumRunnable() { return minimumRunnable; } @Override public int getMaxPoolSize() { return maxPoolSize; } @Override public int getCorePoolSize() { return corePoolSize; } @Override public int getKeepAliveSeconds() { return keepAliveSeconds; } @Override public Predicate getSaturatePredicate() { return saturate; } } DefaultParallelExecutionConfigurationStrategy.java000066400000000000000000000211341455764576500452310ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.math.BigDecimal; import java.util.Locale; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.ConfigurationParameters; /** * Default implementations of configuration strategies for parallel test * execution. * * @since 1.3 */ @API(status = STABLE, since = "1.10") public enum DefaultParallelExecutionConfigurationStrategy implements ParallelExecutionConfigurationStrategy { /** * Uses the mandatory {@value #CONFIG_FIXED_PARALLELISM_PROPERTY_NAME} configuration * parameter as the desired parallelism. */ FIXED { @Override public ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { int parallelism = configurationParameters.get(CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, Integer::valueOf).orElseThrow( () -> new JUnitException(String.format("Configuration parameter '%s' must be set", CONFIG_FIXED_PARALLELISM_PROPERTY_NAME))); int maxPoolSize = configurationParameters.get(CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME, Integer::valueOf).orElse(parallelism + 256); boolean saturate = configurationParameters.get(CONFIG_FIXED_SATURATE_PROPERTY_NAME, Boolean::valueOf).orElse(true); return new DefaultParallelExecutionConfiguration(parallelism, parallelism, maxPoolSize, parallelism, KEEP_ALIVE_SECONDS, __ -> saturate); } }, /** * Computes the desired parallelism based on the number of available * processors/cores multiplied by the {@value #CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME} * configuration parameter. */ DYNAMIC { @Override public ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { BigDecimal factor = configurationParameters.get(CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME, BigDecimal::new).orElse(BigDecimal.ONE); Preconditions.condition(factor.compareTo(BigDecimal.ZERO) > 0, () -> String.format("Factor '%s' specified via configuration parameter '%s' must be greater than 0", factor, CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME)); int parallelism = Math.max(1, factor.multiply(BigDecimal.valueOf(Runtime.getRuntime().availableProcessors())).intValue()); int maxPoolSize = configurationParameters.get(CONFIG_DYNAMIC_MAX_POOL_SIZE_FACTOR_PROPERTY_NAME, BigDecimal::new).map(maxPoolSizeFactor -> { Preconditions.condition(maxPoolSizeFactor.compareTo(BigDecimal.ONE) >= 0, () -> String.format( "Factor '%s' specified via configuration parameter '%s' must be greater than or equal to 1", factor, CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME)); return maxPoolSizeFactor.multiply(BigDecimal.valueOf(parallelism)).intValue(); }).orElseGet(() -> 256 + parallelism); boolean saturate = configurationParameters.get(CONFIG_DYNAMIC_SATURATE_PROPERTY_NAME, Boolean::valueOf).orElse(true); return new DefaultParallelExecutionConfiguration(parallelism, parallelism, maxPoolSize, parallelism, KEEP_ALIVE_SECONDS, __ -> saturate); } }, /** * Allows the specification of a custom {@link ParallelExecutionConfigurationStrategy} * implementation via the mandatory {@value #CONFIG_CUSTOM_CLASS_PROPERTY_NAME} * configuration parameter to determine the desired configuration. */ CUSTOM { @Override public ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { String className = configurationParameters.get(CONFIG_CUSTOM_CLASS_PROPERTY_NAME).orElseThrow( () -> new JUnitException(CONFIG_CUSTOM_CLASS_PROPERTY_NAME + " must be set")); return ReflectionUtils.tryToLoadClass(className) // .andThenTry(strategyClass -> { Preconditions.condition( ParallelExecutionConfigurationStrategy.class.isAssignableFrom(strategyClass), CONFIG_CUSTOM_CLASS_PROPERTY_NAME + " does not implement " + ParallelExecutionConfigurationStrategy.class); return (ParallelExecutionConfigurationStrategy) ReflectionUtils.newInstance(strategyClass); }) // .andThenTry(strategy -> strategy.createConfiguration(configurationParameters)) // .getOrThrow(cause -> new JUnitException( "Could not create configuration for strategy class: " + className, cause)); } }; private static final int KEEP_ALIVE_SECONDS = 30; /** * Property name used to determine the desired configuration strategy. * *

Value must be one of {@code dynamic}, {@code fixed}, or * {@code custom}. */ public static final String CONFIG_STRATEGY_PROPERTY_NAME = "strategy"; /** * Property name used to determine the desired parallelism for the * {@link #FIXED} configuration strategy. * *

No default value; must be an integer. * * @see #FIXED */ public static final String CONFIG_FIXED_PARALLELISM_PROPERTY_NAME = "fixed.parallelism"; /** * Property name used to configure the maximum pool size of the underlying * fork-join pool for the {@link #FIXED} configuration strategy. * *

Value must be an integer and greater than or equal to * {@value #CONFIG_FIXED_PARALLELISM_PROPERTY_NAME}; defaults to * {@code 256 + fixed.parallelism}. * * @since 1.10 * @see #FIXED */ @API(status = EXPERIMENTAL, since = "1.10") public static final String CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME = "fixed.max-pool-size"; /** * Property name used to disable saturation of the underlying fork-join pool * for the {@link #FIXED} configuration strategy. * *

When set to {@code false} the underlying fork-join pool will reject * additional tasks if all available workers are busy and the maximum * pool-size would be exceeded. *

Value must either {@code true} or {@code false}; defaults to {@code true}. * * @since 1.10 * @see #FIXED * @see #CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME */ @API(status = EXPERIMENTAL, since = "1.10") public static final String CONFIG_FIXED_SATURATE_PROPERTY_NAME = "fixed.saturate"; /** * Property name of the factor used to determine the desired parallelism for the * {@link #DYNAMIC} configuration strategy. * *

Value must be a non-negative decimal number; defaults to {@code 1}. * * @see #DYNAMIC */ public static final String CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME = "dynamic.factor"; /** * Property name of the factor used to determine the maximum pool size of * the underlying fork-join pool for the {@link #DYNAMIC} configuration * strategy. * *

Value must be a decimal number equal and greater than or equal to * {@code 1}. When set the maximum pool size is calculated as * {@code dynamic.max-pool-size-factor * dynamic.factor * Runtime.getRuntime().availableProcessors()} * When not set the maximum pool size is calculated as * {@code 256 + dynamic.factor * Runtime.getRuntime().availableProcessors()} * instead. * * @since 1.10 * @see #DYNAMIC */ @API(status = EXPERIMENTAL, since = "1.10") public static final String CONFIG_DYNAMIC_MAX_POOL_SIZE_FACTOR_PROPERTY_NAME = "dynamic.max-pool-size-factor"; /** * Property name used to disable saturation of the underlying fork-join pool * for the {@link #DYNAMIC} configuration strategy. * *

When set to {@code false} the underlying fork-join pool will reject * additional tasks if all available workers are busy and the maximum * pool-size would be exceeded. *

Value must either {@code true} or {@code false}; defaults to {@code true}. * * @since 1.10 * @see #DYNAMIC * @see #CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME */ @API(status = EXPERIMENTAL, since = "1.10") public static final String CONFIG_DYNAMIC_SATURATE_PROPERTY_NAME = "dynamic.saturate"; /** * Property name used to specify the fully qualified class name of the * {@link ParallelExecutionConfigurationStrategy} to be used by the * {@link #CUSTOM} configuration strategy. * * @see #CUSTOM */ public static final String CONFIG_CUSTOM_CLASS_PROPERTY_NAME = "custom.class"; static ParallelExecutionConfigurationStrategy getStrategy(ConfigurationParameters configurationParameters) { return valueOf( configurationParameters.get(CONFIG_STRATEGY_PROPERTY_NAME).orElse("dynamic").toUpperCase(Locale.ROOT)); } } EngineExecutionContext.java000066400000000000000000000013471455764576500404730ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; /** * Marker interface for an execution context used by a concrete implementation * of {@link HierarchicalTestEngine} and its collaborators. * * @since 1.0 * @see HierarchicalTestEngine */ @API(status = MAINTAINED, since = "1.0") public interface EngineExecutionContext { } ExclusiveResource.java000066400000000000000000000072061455764576500375140ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; import java.util.concurrent.locks.ReadWriteLock; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; /** * An exclusive resource identified by a key with a lock mode that is used to * synchronize access to shared resources when executing nodes in parallel. * * @since 1.3 * @see Node#getExecutionMode() */ @API(status = STABLE, since = "1.10") public class ExclusiveResource { /** * Key of the global resource lock that all direct children of the engine * descriptor acquire in {@linkplain LockMode#READ read mode} by default: * {@value} * *

If any node {@linkplain Node#getExclusiveResources() requires} an * exclusive resource with the same key in * {@linkplain LockMode#READ_WRITE read-write mode}, the lock will be * coarsened to be acquired by the node's ancestor that is a direct child of * the engine descriptor and all of the ancestor's descendants will be * forced to run in the {@linkplain ExecutionMode#SAME_THREAD same thread}. * * @since 1.7 */ @API(status = STABLE, since = "1.10") public static final String GLOBAL_KEY = "org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_KEY"; static final ExclusiveResource GLOBAL_READ = new ExclusiveResource(GLOBAL_KEY, LockMode.READ); static final ExclusiveResource GLOBAL_READ_WRITE = new ExclusiveResource(GLOBAL_KEY, LockMode.READ_WRITE); private final String key; private final LockMode lockMode; private int hash; /** * Create a new {@code ExclusiveResource}. * * @param key the identifier of the resource; never {@code null} or blank * @param lockMode the lock mode to use to synchronize access to the * resource; never {@code null} */ public ExclusiveResource(String key, LockMode lockMode) { this.key = Preconditions.notBlank(key, "key must not be blank"); this.lockMode = Preconditions.notNull(lockMode, "lockMode must not be null"); } /** * Get the key of this resource. */ public String getKey() { return key; } /** * Get the lock mode of this resource. */ public LockMode getLockMode() { return lockMode; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ExclusiveResource that = (ExclusiveResource) o; return Objects.equals(key, that.key) && lockMode == that.lockMode; } @Override public int hashCode() { int h = hash; if (h == 0) { h = hash = Objects.hash(key, lockMode); } return h; } @Override public String toString() { return new ToStringBuilder(this).append("key", key).append("lockMode", lockMode).toString(); } /** * {@code LockMode} translates to the respective {@link ReadWriteLock} * locks. * * @implNote Enum order is important, since it can be used to sort locks, so * the stronger mode has to be first. */ public enum LockMode { /** * Require read and write access to the resource. * * @see ReadWriteLock#writeLock() */ READ_WRITE, /** * Require only read access to the resource. * * @see ReadWriteLock#readLock() */ READ } } ForkJoinPoolHierarchicalTestExecutorService.java000066400000000000000000000211311455764576500446000ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.concurrent.CompletableFuture.completedFuture; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.CONCURRENT; import java.lang.Thread.UncaughtExceptionHandler; import java.lang.reflect.Constructor; import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.Future; import java.util.concurrent.RecursiveAction; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.ConfigurationParameters; /** * A {@link ForkJoinPool}-based * {@linkplain HierarchicalTestExecutorService executor service} that executes * {@linkplain TestTask test tasks} with the configured parallelism. * * @since 1.3 * @see ForkJoinPool * @see DefaultParallelExecutionConfigurationStrategy */ @API(status = STABLE, since = "1.10") public class ForkJoinPoolHierarchicalTestExecutorService implements HierarchicalTestExecutorService { private final ForkJoinPool forkJoinPool; private final int parallelism; /** * Create a new {@code ForkJoinPoolHierarchicalTestExecutorService} based on * the supplied {@link ConfigurationParameters}. * * @see DefaultParallelExecutionConfigurationStrategy */ public ForkJoinPoolHierarchicalTestExecutorService(ConfigurationParameters configurationParameters) { this(createConfiguration(configurationParameters)); } /** * Create a new {@code ForkJoinPoolHierarchicalTestExecutorService} based on * the supplied {@link ParallelExecutionConfiguration}. * * @since 1.7 */ @API(status = STABLE, since = "1.10") public ForkJoinPoolHierarchicalTestExecutorService(ParallelExecutionConfiguration configuration) { forkJoinPool = createForkJoinPool(configuration); parallelism = forkJoinPool.getParallelism(); LoggerFactory.getLogger(getClass()).config(() -> "Using ForkJoinPool with parallelism of " + parallelism); } private static ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.getStrategy( configurationParameters); return strategy.createConfiguration(configurationParameters); } private ForkJoinPool createForkJoinPool(ParallelExecutionConfiguration configuration) { ForkJoinWorkerThreadFactory threadFactory = new WorkerThreadFactory(); // Try to use constructor available in Java >= 9 Callable constructorInvocation = sinceJava9Constructor() // .map(sinceJava9ConstructorInvocation(configuration, threadFactory)) // Fallback for Java 8 .orElse(sinceJava7ConstructorInvocation(configuration, threadFactory)); return Try.call(constructorInvocation) // .getOrThrow(cause -> new JUnitException("Failed to create ForkJoinPool", cause)); } private static Optional> sinceJava9Constructor() { return Try.call(() -> ForkJoinPool.class.getDeclaredConstructor(Integer.TYPE, ForkJoinWorkerThreadFactory.class, UncaughtExceptionHandler.class, Boolean.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, Predicate.class, Long.TYPE, TimeUnit.class)) // .toOptional(); } private static Function, Callable> sinceJava9ConstructorInvocation( ParallelExecutionConfiguration configuration, ForkJoinWorkerThreadFactory threadFactory) { return constructor -> () -> constructor.newInstance(configuration.getParallelism(), threadFactory, null, false, configuration.getCorePoolSize(), configuration.getMaxPoolSize(), configuration.getMinimumRunnable(), configuration.getSaturatePredicate(), configuration.getKeepAliveSeconds(), TimeUnit.SECONDS); } private static Callable sinceJava7ConstructorInvocation(ParallelExecutionConfiguration configuration, ForkJoinWorkerThreadFactory threadFactory) { return () -> new ForkJoinPool(configuration.getParallelism(), threadFactory, null, false); } @Override public Future submit(TestTask testTask) { ExclusiveTask exclusiveTask = new ExclusiveTask(testTask); if (!isAlreadyRunningInForkJoinPool()) { // ensure we're running inside the ForkJoinPool so we // can use ForkJoinTask API in invokeAll etc. return forkJoinPool.submit(exclusiveTask); } // Limit the amount of queued work so we don't consume dynamic tests too eagerly // by forking only if the current worker thread's queue length is below the // desired parallelism. This optimistically assumes that the already queued tasks // can be stolen by other workers and the new task requires about the same // execution time as the already queued tasks. If the other workers are busy, // the parallelism is already at its desired level. If all already queued tasks // can be stolen by otherwise idle workers and the new task takes significantly // longer, parallelism will drop. However, that only happens if the enclosing test // task is the only one remaining which should rarely be the case. if (testTask.getExecutionMode() == CONCURRENT && ForkJoinTask.getSurplusQueuedTaskCount() < parallelism) { return exclusiveTask.fork(); } exclusiveTask.compute(); return completedFuture(null); } private boolean isAlreadyRunningInForkJoinPool() { return ForkJoinTask.getPool() == forkJoinPool; } @Override public void invokeAll(List tasks) { if (tasks.size() == 1) { new ExclusiveTask(tasks.get(0)).compute(); return; } Deque nonConcurrentTasks = new LinkedList<>(); Deque concurrentTasksInReverseOrder = new LinkedList<>(); forkConcurrentTasks(tasks, nonConcurrentTasks, concurrentTasksInReverseOrder); executeNonConcurrentTasks(nonConcurrentTasks); joinConcurrentTasksInReverseOrderToEnableWorkStealing(concurrentTasksInReverseOrder); } private void forkConcurrentTasks(List tasks, Deque nonConcurrentTasks, Deque concurrentTasksInReverseOrder) { for (TestTask testTask : tasks) { ExclusiveTask exclusiveTask = new ExclusiveTask(testTask); if (testTask.getExecutionMode() == CONCURRENT) { exclusiveTask.fork(); concurrentTasksInReverseOrder.addFirst(exclusiveTask); } else { nonConcurrentTasks.add(exclusiveTask); } } } private void executeNonConcurrentTasks(Deque nonConcurrentTasks) { for (ExclusiveTask task : nonConcurrentTasks) { task.compute(); } } private void joinConcurrentTasksInReverseOrderToEnableWorkStealing( Deque concurrentTasksInReverseOrder) { for (ExclusiveTask forkedTask : concurrentTasksInReverseOrder) { forkedTask.join(); } } @Override public void close() { forkJoinPool.shutdownNow(); } // this class cannot not be serialized because TestTask is not Serializable @SuppressWarnings("serial") static class ExclusiveTask extends RecursiveAction { private final TestTask testTask; ExclusiveTask(TestTask testTask) { this.testTask = testTask; } @SuppressWarnings("try") @Override public void compute() { try (ResourceLock lock = testTask.getResourceLock().acquire()) { testTask.execute(); } catch (InterruptedException e) { ExceptionUtils.throwAsUncheckedException(e); } } } static class WorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory { private final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); @Override public ForkJoinWorkerThread newThread(ForkJoinPool pool) { return new WorkerThread(pool, contextClassLoader); } } static class WorkerThread extends ForkJoinWorkerThread { WorkerThread(ForkJoinPool pool, ClassLoader contextClassLoader) { super(pool); setContextClassLoader(contextClassLoader); } } } HierarchicalTestEngine.java000066400000000000000000000105161455764576500403770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestEngine; /** * Abstract base class for all {@link TestEngine} implementations that wish * to organize test suites hierarchically based on the {@link Node} abstraction. * * @param the type of {@code EngineExecutionContext} used by this engine * @since 1.0 * @see Node */ @API(status = MAINTAINED, since = "1.0") public abstract class HierarchicalTestEngine implements TestEngine { public HierarchicalTestEngine() { } /** * Create an {@linkplain #createExecutorService(ExecutionRequest) executor * service}; create an initial {@linkplain #createExecutionContext execution * context}; execute the behavior of all {@linkplain Node nodes} in the * hierarchy starting with the supplied {@code request}'s * {@linkplain ExecutionRequest#getRootTestDescriptor() root} and notify * its {@linkplain ExecutionRequest#getEngineExecutionListener() execution * listener} of test execution events. * * @see Node * @see #createExecutorService * @see #createExecutionContext */ @Override public final void execute(ExecutionRequest request) { try (HierarchicalTestExecutorService executorService = createExecutorService(request)) { C executionContext = createExecutionContext(request); ThrowableCollector.Factory throwableCollectorFactory = createThrowableCollectorFactory(request); new HierarchicalTestExecutor<>(request, executionContext, executorService, throwableCollectorFactory).execute().get(); } catch (Exception exception) { throw new JUnitException("Error executing tests for engine " + getId(), exception); } } /** * Create the {@linkplain HierarchicalTestExecutorService executor service} * to use for executing the supplied {@linkplain ExecutionRequest request}. * *

An engine may use the information in the supplied request * such as the contained * {@linkplain ExecutionRequest#getConfigurationParameters() configuration parameters} * to decide what kind of service to return or how to configure it. * *

By default, this method returns an instance of * {@link SameThreadHierarchicalTestExecutorService}. * * @param request the request about to be executed * @since 1.3 * @see ForkJoinPoolHierarchicalTestExecutorService * @see SameThreadHierarchicalTestExecutorService */ @API(status = STABLE, since = "1.10") protected HierarchicalTestExecutorService createExecutorService(ExecutionRequest request) { return new SameThreadHierarchicalTestExecutorService(); } /** * Create the {@linkplain ThrowableCollector.Factory factory} for creating * {@link ThrowableCollector} instances used to handle exceptions that occur * during execution of this engine's tests. * *

An engine may use the information in the supplied request * such as the contained * {@linkplain ExecutionRequest#getConfigurationParameters() configuration parameters} * to decide what kind of factory to return or how to configure it. * *

By default, this method returns a factory that always creates instances of * {@link OpenTest4JAwareThrowableCollector}. * * @param request the request about to be executed * @since 1.3 * @see OpenTest4JAwareThrowableCollector * @see ThrowableCollector */ @API(status = STABLE, since = "1.10") protected ThrowableCollector.Factory createThrowableCollectorFactory(ExecutionRequest request) { return OpenTest4JAwareThrowableCollector::new; } /** * Create the initial execution context for executing the supplied * {@linkplain ExecutionRequest request}. * * @param request the request about to be executed * @return the initial context that will be passed to nodes in the hierarchy */ protected abstract C createExecutionContext(ExecutionRequest request); } HierarchicalTestExecutor.java000066400000000000000000000046271455764576500407760ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.concurrent.Future; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; /** * Implementation core of all {@link TestEngine TestEngines} that wish to * use the {@link Node} abstraction as the driving principle for structuring * and executing test suites. * *

A {@code HierarchicalTestExecutor} is instantiated by a concrete * implementation of {@link HierarchicalTestEngine} and takes care of * executing nodes in the hierarchy in the appropriate order as well as * firing the necessary events in the {@link EngineExecutionListener}. * * @param the type of {@code EngineExecutionContext} used by the * {@code HierarchicalTestEngine} * @since 1.0 */ class HierarchicalTestExecutor { private final ExecutionRequest request; private final C rootContext; private final HierarchicalTestExecutorService executorService; private final ThrowableCollector.Factory throwableCollectorFactory; HierarchicalTestExecutor(ExecutionRequest request, C rootContext, HierarchicalTestExecutorService executorService, ThrowableCollector.Factory throwableCollectorFactory) { this.request = request; this.rootContext = rootContext; this.executorService = executorService; this.throwableCollectorFactory = throwableCollectorFactory; } Future execute() { TestDescriptor rootTestDescriptor = this.request.getRootTestDescriptor(); EngineExecutionListener executionListener = this.request.getEngineExecutionListener(); NodeExecutionAdvisor executionAdvisor = new NodeTreeWalker().walk(rootTestDescriptor); NodeTestTaskContext taskContext = new NodeTestTaskContext(executionListener, this.executorService, this.throwableCollectorFactory, executionAdvisor); NodeTestTask rootTestTask = new NodeTestTask<>(taskContext, rootTestDescriptor); rootTestTask.setParentContext(this.rootContext); return this.executorService.submit(rootTestTask); } } HierarchicalTestExecutorService.java000066400000000000000000000062111455764576500423060ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import java.util.concurrent.Future; import org.apiguardian.api.API; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; /** * A closeable service that executes {@linkplain TestTask test tasks}. * * @since 1.3 * @see HierarchicalTestEngine#createExecutorService(ExecutionRequest) * @see SameThreadHierarchicalTestExecutorService * @see ForkJoinPoolHierarchicalTestExecutorService */ @API(status = STABLE, since = "1.10") public interface HierarchicalTestExecutorService extends AutoCloseable { /** * Submit the supplied {@linkplain TestTask test task} to be executed by * this service. * *

Implementations may {@linkplain TestTask#execute() execute} the task * asynchronously as long as its * {@linkplain TestTask#getExecutionMode() execution mode} is * {@linkplain ExecutionMode#CONCURRENT concurrent}. * *

Implementations must generally acquire and release the task's * {@linkplain TestTask#getResourceLock() resource lock} before and after its * execution unless they execute all tests in the same thread which * upholds the same guarantees. * * @param testTask the test task to be executed * @return a future that the caller can use to wait for the task's execution * to be finished * @see #invokeAll(List) */ Future submit(TestTask testTask); /** * Invoke all supplied {@linkplain TestTask test tasks} and block until * their execution has finished. * *

Implementations may {@linkplain TestTask#execute() execute} one or * multiple of the supplied tasks in parallel as long as their * {@linkplain TestTask#getExecutionMode() execution mode} is * {@linkplain ExecutionMode#CONCURRENT concurrent}. * *

Implementations must generally acquire and release each task's * {@linkplain TestTask#getResourceLock() resource lock} before and after its * execution unless they execute all tests in the same thread which * upholds the same guarantees. * * @param testTasks the test tasks to be executed * @see #submit(TestTask) */ void invokeAll(List testTasks); /** * Close this service and let it perform any required cleanup work. * *

For example, thread-based implementations should usually close their * thread pools in this method. */ @Override void close(); /** * An executable task that represents a single test or container. */ interface TestTask { /** * Get the {@linkplain ExecutionMode execution mode} of this task. */ ExecutionMode getExecutionMode(); /** * Get the {@linkplain ResourceLock resource lock} of this task. */ ResourceLock getResourceLock(); /** * Execute this task. */ void execute(); } } LockManager.java000066400000000000000000000055751455764576500362270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.Comparator.comparing; import static java.util.Comparator.naturalOrder; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_KEY; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ; import java.util.Collection; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @since 1.3 */ class LockManager { private static final Comparator COMPARATOR // = comparing(ExclusiveResource::getKey, globalKeyFirst().thenComparing(naturalOrder())) // .thenComparing(ExclusiveResource::getLockMode); private static Comparator globalKeyFirst() { return comparing(key -> !GLOBAL_KEY.equals(key)); } private final Map locksByKey = new ConcurrentHashMap<>(); ResourceLock getLockForResources(Collection resources) { if (resources.size() == 1) { return getLockForResource(getOnlyElement(resources)); } List locks = getDistinctSortedLocks(resources); return toResourceLock(locks); } ResourceLock getLockForResource(ExclusiveResource resource) { return new SingleLock(toLock(resource)); } private List getDistinctSortedLocks(Collection resources) { // @formatter:off Map> resourcesByKey = resources.stream() .sorted(COMPARATOR) .distinct() .collect(groupingBy(ExclusiveResource::getKey, LinkedHashMap::new, toList())); return resourcesByKey.values().stream() .map(resourcesWithSameKey -> resourcesWithSameKey.get(0)) .map(this::toLock) .collect(toList()); // @formatter:on } private Lock toLock(ExclusiveResource resource) { ReadWriteLock lock = this.locksByKey.computeIfAbsent(resource.getKey(), key -> new ReentrantReadWriteLock()); return resource.getLockMode() == READ ? lock.readLock() : lock.writeLock(); } private ResourceLock toResourceLock(List locks) { switch (locks.size()) { case 0: return NopLock.INSTANCE; case 1: return new SingleLock(locks.get(0)); default: return new CompositeLock(locks); } } } Node.java000066400000000000000000000247751455764576500347340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.Collections.emptySet; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import java.util.Set; import java.util.concurrent.Future; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; /** * A node within the execution hierarchy. * * @param the type of {@code EngineExecutionContext} used by the * {@code HierarchicalTestEngine} * @since 1.0 * @see HierarchicalTestEngine */ @API(status = MAINTAINED, since = "1.0", consumers = "org.junit.platform.engine.support.hierarchical") public interface Node { /** * Prepare the supplied {@code context} prior to execution. * *

The default implementation returns the supplied {@code context} unmodified. * * @see #cleanUp(EngineExecutionContext) */ default C prepare(C context) throws Exception { return context; } /** * Clean up the supplied {@code context} after execution. * *

The default implementation does nothing. * * @param context the context to execute in * @since 1.1 * @see #prepare(EngineExecutionContext) */ default void cleanUp(C context) throws Exception { } /** * Determine if the execution of the supplied {@code context} should be * skipped. * *

The default implementation returns {@link SkipResult#doNotSkip()}. */ default SkipResult shouldBeSkipped(C context) throws Exception { return SkipResult.doNotSkip(); } /** * Execute the before behavior of this node. * *

This method will be called once before {@linkplain #execute * execution} of this node. * *

The default implementation returns the supplied {@code context} unmodified. * * @param context the context to execute in * @return the new context to be used for children of this node; never * {@code null} * @see #execute(EngineExecutionContext, DynamicTestExecutor) * @see #after(EngineExecutionContext) */ default C before(C context) throws Exception { return context; } /** * Execute the behavior of this node. * *

Containers typically do not implement this method since the * {@link HierarchicalTestEngine} handles execution of their children. * *

The supplied {@code dynamicTestExecutor} may be used to submit * additional dynamic tests for immediate execution. * *

The default implementation returns the supplied {@code context} unmodified. * * @param context the context to execute in * @param dynamicTestExecutor the executor to submit dynamic tests to * @return the new context to be used for children of this node and for the * after behavior of the parent of this node, if any * @see #before * @see #after */ default C execute(C context, DynamicTestExecutor dynamicTestExecutor) throws Exception { return context; } /** * Execute the after behavior of this node. * *

This method will be called once after {@linkplain #execute * execution} of this node. * *

The default implementation does nothing. * * @param context the context to execute in * @see #before * @see #execute */ default void after(C context) throws Exception { } /** * Wraps around the invocation of {@link #before(EngineExecutionContext)}, * {@link #execute(EngineExecutionContext, DynamicTestExecutor)}, and * {@link #after(EngineExecutionContext)}. * * @param context context the context to execute in * @param invocation the wrapped invocation (must be invoked exactly once) * @since 1.4 */ @API(status = STABLE, since = "1.10") default void around(C context, Invocation invocation) throws Exception { invocation.invoke(context); } /** * Callback invoked when the execution of this node has been skipped. * *

The default implementation does nothing. * * @param context the execution context * @param testDescriptor the test descriptor that was skipped * @param result the result of skipped execution * @since 1.4 */ @API(status = STABLE, since = "1.10", consumers = "org.junit.platform.engine.support.hierarchical") default void nodeSkipped(C context, TestDescriptor testDescriptor, SkipResult result) { } /** * Callback invoked when the execution of this node has finished. * *

The default implementation does nothing. * * @param context the execution context * @param testDescriptor the test descriptor that was executed * @param result the result of the execution * @since 1.4 */ @API(status = STABLE, since = "1.10", consumers = "org.junit.platform.engine.support.hierarchical") default void nodeFinished(C context, TestDescriptor testDescriptor, TestExecutionResult result) { } /** * Get the set of {@linkplain ExclusiveResource exclusive resources} * required to execute this node. * *

The default implementation returns an empty set. * * @return the set of exclusive resources required by this node; never * {@code null} but potentially empty * @since 1.3 * @see ExclusiveResource */ @API(status = STABLE, since = "1.10", consumers = "org.junit.platform.engine.support.hierarchical") default Set getExclusiveResources() { return emptySet(); } /** * Get the preferred of {@linkplain ExecutionMode execution mode} for * parallel execution of this node. * *

The default implementation returns {@link ExecutionMode#CONCURRENT}. * * @return the preferred execution mode of this node; never {@code null} * @since 1.3 * @see ExecutionMode */ @API(status = STABLE, since = "1.10", consumers = "org.junit.platform.engine.support.hierarchical") default ExecutionMode getExecutionMode() { return ExecutionMode.CONCURRENT; } /** * The result of determining whether the execution of a given {@code context} * should be skipped. * * @see Node#shouldBeSkipped(EngineExecutionContext) */ class SkipResult { private static final SkipResult alwaysExecuteSkipResult = new SkipResult(false, null); private final boolean skipped; private final Optional reason; /** * Factory for creating skipped results. * *

A context that is skipped will be not be executed. * * @param reason the reason that the context should be skipped, * may be {@code null} * @return a skipped {@code SkipResult} with the given reason */ public static SkipResult skip(String reason) { return new SkipResult(true, reason); } /** * Factory for creating do not skip results. * *

A context that is not skipped will be executed as normal. * * @return a do not skip {@code SkipResult} */ public static SkipResult doNotSkip() { return alwaysExecuteSkipResult; } private SkipResult(boolean skipped, String reason) { this.skipped = skipped; this.reason = Optional.ofNullable(reason); } /** * Whether execution of the context should be skipped. * * @return {@code true} if the execution should be skipped */ public boolean isSkipped() { return this.skipped; } /** * Get the reason that execution of the context should be skipped, * if available. */ public Optional getReason() { return this.reason; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("skipped", this.skipped) .append("reason", this.reason.orElse("")) .toString(); // @formatter:on } } /** * Executor for additional, dynamic test descriptors discovered during * execution of a {@link Node}. * *

The test descriptors will be executed by the same * {@link HierarchicalTestExecutor} that executes the submitting node. * *

This interface is not intended to be implemented by clients. * * @see Node#execute(EngineExecutionContext, DynamicTestExecutor) * @see HierarchicalTestExecutor */ interface DynamicTestExecutor { /** * Submit a dynamic test descriptor for immediate execution. * * @param testDescriptor the test descriptor to be executed; never * {@code null} */ void execute(TestDescriptor testDescriptor); /** * Submit a dynamic test descriptor for immediate execution with a * custom, potentially no-op, execution listener. * * @param testDescriptor the test descriptor to be executed; never * {@code null} * @param executionListener the executionListener to be notified; never * {@code null} * @return a future to cancel or wait for the execution * @since 1.7 * @see EngineExecutionListener#NOOP */ @API(status = STABLE, since = "1.10") Future execute(TestDescriptor testDescriptor, EngineExecutionListener executionListener); /** * Block until all dynamic test descriptors submitted to this executor * are finished. * *

This method is useful if the node needs to perform actions in its * {@link #execute(EngineExecutionContext, DynamicTestExecutor)} method * after all its dynamic children have finished. * * @throws InterruptedException if interrupted while waiting */ void awaitFinished() throws InterruptedException; } /** * Supported execution modes for parallel execution. * * @since 1.3 * @see #SAME_THREAD * @see #CONCURRENT * @see Node#getExecutionMode() */ @API(status = STABLE, since = "1.10", consumers = "org.junit.platform.engine.support.hierarchical") enum ExecutionMode { /** * Force execution in same thread as the parent node. * * @see #CONCURRENT */ SAME_THREAD, /** * Allow concurrent execution with any other node. * * @see #SAME_THREAD */ CONCURRENT } /** * Represents an invocation that runs with the supplied context. * * @param the type of {@code EngineExecutionContext} used by the {@code HierarchicalTestEngine} * @since 1.4 */ @API(status = STABLE, since = "1.10") interface Invocation { /** * Invoke this invocation with the supplied context. * * @param context the context to invoke in */ void invoke(C context) throws Exception; } } NodeExecutionAdvisor.java000066400000000000000000000034701455764576500401350ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.HashMap; import java.util.Map; import java.util.Optional; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; /** * @since 1.3.1 */ class NodeExecutionAdvisor { private final Map forcedDescendantExecutionModeByTestDescriptor = new HashMap<>(); private final Map resourceLocksByTestDescriptor = new HashMap<>(); void forceDescendantExecutionMode(TestDescriptor testDescriptor, ExecutionMode executionMode) { forcedDescendantExecutionModeByTestDescriptor.put(testDescriptor, executionMode); } void useResourceLock(TestDescriptor testDescriptor, ResourceLock resourceLock) { resourceLocksByTestDescriptor.put(testDescriptor, resourceLock); } Optional getForcedExecutionMode(TestDescriptor testDescriptor) { return testDescriptor.getParent().flatMap(this::lookupExecutionModeForcedByAncestor); } private Optional lookupExecutionModeForcedByAncestor(TestDescriptor testDescriptor) { ExecutionMode value = forcedDescendantExecutionModeByTestDescriptor.get(testDescriptor); if (value != null) { return Optional.of(value); } return testDescriptor.getParent().flatMap(this::lookupExecutionModeForcedByAncestor); } ResourceLock getResourceLock(TestDescriptor testDescriptor) { return resourceLocksByTestDescriptor.getOrDefault(testDescriptor, NopLock.INSTANCE); } } NodeTestTask.java000066400000000000000000000217531455764576500364100ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.concurrent.CompletableFuture.completedFuture; import static java.util.stream.Collectors.toCollection; import static org.junit.platform.engine.TestExecutionResult.failed; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService.TestTask; import org.junit.platform.engine.support.hierarchical.Node.DynamicTestExecutor; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; import org.junit.platform.engine.support.hierarchical.Node.SkipResult; /** * @since 1.3 */ class NodeTestTask implements TestTask { private static final Logger logger = LoggerFactory.getLogger(NodeTestTask.class); private static final Runnable NOOP = () -> { }; private final NodeTestTaskContext taskContext; private final TestDescriptor testDescriptor; private final Node node; private final Runnable finalizer; private C parentContext; private C context; private SkipResult skipResult; private boolean started; private ThrowableCollector throwableCollector; NodeTestTask(NodeTestTaskContext taskContext, TestDescriptor testDescriptor) { this(taskContext, testDescriptor, NOOP); } NodeTestTask(NodeTestTaskContext taskContext, TestDescriptor testDescriptor, Runnable finalizer) { this.taskContext = taskContext; this.testDescriptor = testDescriptor; this.node = NodeUtils.asNode(testDescriptor); this.finalizer = finalizer; } @Override public ResourceLock getResourceLock() { return taskContext.getExecutionAdvisor().getResourceLock(testDescriptor); } @Override public ExecutionMode getExecutionMode() { return taskContext.getExecutionAdvisor().getForcedExecutionMode(testDescriptor).orElse(node.getExecutionMode()); } void setParentContext(C parentContext) { this.parentContext = parentContext; } @Override public void execute() { try { throwableCollector = taskContext.getThrowableCollectorFactory().create(); prepare(); if (throwableCollector.isEmpty()) { checkWhetherSkipped(); } if (throwableCollector.isEmpty() && !skipResult.isSkipped()) { executeRecursively(); } if (context != null) { cleanUp(); } reportCompletion(); } finally { // Ensure that the 'interrupted status' flag for the current thread // is cleared for reuse of the thread in subsequent task executions. // See https://github.com/junit-team/junit5/issues/1688 if (Thread.interrupted()) { logger.debug(() -> String.format( "Execution of TestDescriptor with display name [%s] " + "and unique ID [%s] failed to clear the 'interrupted status' flag for the " + "current thread. JUnit has cleared the flag, but you may wish to investigate " + "why the flag was not cleared by user code.", this.testDescriptor.getDisplayName(), this.testDescriptor.getUniqueId())); } finalizer.run(); } // Clear reference to context to allow it to be garbage collected. // See https://github.com/junit-team/junit5/issues/1578 context = null; } private void prepare() { throwableCollector.execute(() -> context = node.prepare(parentContext)); // Clear reference to parent context to allow it to be garbage collected. // See https://github.com/junit-team/junit5/issues/1578 parentContext = null; } private void checkWhetherSkipped() { throwableCollector.execute(() -> skipResult = node.shouldBeSkipped(context)); } private void executeRecursively() { taskContext.getListener().executionStarted(testDescriptor); started = true; throwableCollector.execute(() -> { node.around(context, ctx -> { context = ctx; throwableCollector.execute(() -> { // @formatter:off List> children = testDescriptor.getChildren().stream() .map(descriptor -> new NodeTestTask(taskContext, descriptor)) .collect(toCollection(ArrayList::new)); // @formatter:on context = node.before(context); final DynamicTestExecutor dynamicTestExecutor = new DefaultDynamicTestExecutor(); context = node.execute(context, dynamicTestExecutor); if (!children.isEmpty()) { children.forEach(child -> child.setParentContext(context)); taskContext.getExecutorService().invokeAll(children); } throwableCollector.execute(dynamicTestExecutor::awaitFinished); }); throwableCollector.execute(() -> node.after(context)); }); }); } private void cleanUp() { throwableCollector.execute(() -> node.cleanUp(context)); } private void reportCompletion() { if (throwableCollector.isEmpty() && skipResult.isSkipped()) { try { node.nodeSkipped(context, testDescriptor, skipResult); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.debug(throwable, () -> String.format("Failed to invoke nodeSkipped() on Node %s", testDescriptor.getUniqueId())); } taskContext.getListener().executionSkipped(testDescriptor, skipResult.getReason().orElse("")); return; } if (!started) { // Call executionStarted first to comply with the contract of EngineExecutionListener. taskContext.getListener().executionStarted(testDescriptor); } try { node.nodeFinished(context, testDescriptor, throwableCollector.toTestExecutionResult()); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.debug(throwable, () -> String.format("Failed to invoke nodeFinished() on Node %s", testDescriptor.getUniqueId())); } taskContext.getListener().executionFinished(testDescriptor, throwableCollector.toTestExecutionResult()); throwableCollector = null; } private class DefaultDynamicTestExecutor implements DynamicTestExecutor { private final Map unfinishedTasks = new ConcurrentHashMap<>(); @Override public void execute(TestDescriptor testDescriptor) { execute(testDescriptor, taskContext.getListener()); } @Override public Future execute(TestDescriptor testDescriptor, EngineExecutionListener executionListener) { Preconditions.notNull(testDescriptor, "testDescriptor must not be null"); Preconditions.notNull(executionListener, "executionListener must not be null"); executionListener.dynamicTestRegistered(testDescriptor); Set exclusiveResources = NodeUtils.asNode(testDescriptor).getExclusiveResources(); if (!exclusiveResources.isEmpty()) { executionListener.executionStarted(testDescriptor); String message = "Dynamic test descriptors must not declare exclusive resources: " + exclusiveResources; executionListener.executionFinished(testDescriptor, failed(new JUnitException(message))); return completedFuture(null); } else { UniqueId uniqueId = testDescriptor.getUniqueId(); NodeTestTask nodeTestTask = new NodeTestTask<>(taskContext.withListener(executionListener), testDescriptor, () -> unfinishedTasks.remove(uniqueId)); nodeTestTask.setParentContext(context); unfinishedTasks.put(uniqueId, DynamicTaskState.unscheduled()); Future future = taskContext.getExecutorService().submit(nodeTestTask); unfinishedTasks.computeIfPresent(uniqueId, (__, state) -> DynamicTaskState.scheduled(future)); return future; } } @Override public void awaitFinished() throws InterruptedException { for (DynamicTaskState state : unfinishedTasks.values()) { try { state.awaitFinished(); } catch (CancellationException ignore) { // Futures returned by execute() may have been cancelled } catch (ExecutionException e) { ExceptionUtils.throwAsUncheckedException(e.getCause()); } } } } @FunctionalInterface private interface DynamicTaskState { DynamicTaskState UNSCHEDULED = () -> { }; static DynamicTaskState unscheduled() { return UNSCHEDULED; } static DynamicTaskState scheduled(Future future) { return future::get; } void awaitFinished() throws CancellationException, ExecutionException, InterruptedException; } } NodeTestTaskContext.java000066400000000000000000000032121455764576500377430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import org.junit.platform.engine.EngineExecutionListener; /** * @since 1.3.1 */ class NodeTestTaskContext { private final EngineExecutionListener listener; private final HierarchicalTestExecutorService executorService; private final ThrowableCollector.Factory throwableCollectorFactory; private final NodeExecutionAdvisor executionAdvisor; public NodeTestTaskContext(EngineExecutionListener listener, HierarchicalTestExecutorService executorService, ThrowableCollector.Factory throwableCollectorFactory, NodeExecutionAdvisor executionAdvisor) { this.listener = listener; this.executorService = executorService; this.throwableCollectorFactory = throwableCollectorFactory; this.executionAdvisor = executionAdvisor; } NodeTestTaskContext withListener(EngineExecutionListener listener) { if (this.listener == listener) { return this; } return new NodeTestTaskContext(listener, executorService, throwableCollectorFactory, executionAdvisor); } EngineExecutionListener getListener() { return listener; } HierarchicalTestExecutorService getExecutorService() { return executorService; } ThrowableCollector.Factory getThrowableCollectorFactory() { return throwableCollectorFactory; } NodeExecutionAdvisor getExecutionAdvisor() { return executionAdvisor; } } NodeTreeWalker.java000066400000000000000000000077511455764576500367150ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ_WRITE; import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.SAME_THREAD; import java.util.HashSet; import java.util.Set; import java.util.function.Consumer; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; /** * @since 1.3 */ class NodeTreeWalker { private final LockManager lockManager; private final ResourceLock globalReadLock; private final ResourceLock globalReadWriteLock; NodeTreeWalker() { this(new LockManager()); } NodeTreeWalker(LockManager lockManager) { this.lockManager = lockManager; this.globalReadLock = lockManager.getLockForResource(GLOBAL_READ); this.globalReadWriteLock = lockManager.getLockForResource(GLOBAL_READ_WRITE); } NodeExecutionAdvisor walk(TestDescriptor rootDescriptor) { Preconditions.condition(getExclusiveResources(rootDescriptor).isEmpty(), "Engine descriptor must not declare exclusive resources"); NodeExecutionAdvisor advisor = new NodeExecutionAdvisor(); rootDescriptor.getChildren().forEach(child -> walk(child, child, advisor)); return advisor; } private void walk(TestDescriptor globalLockDescriptor, TestDescriptor testDescriptor, NodeExecutionAdvisor advisor) { Set exclusiveResources = getExclusiveResources(testDescriptor); if (exclusiveResources.isEmpty()) { advisor.useResourceLock(testDescriptor, globalReadLock); testDescriptor.getChildren().forEach(child -> walk(globalLockDescriptor, child, advisor)); } else { Set allResources = new HashSet<>(exclusiveResources); if (isReadOnly(allResources)) { doForChildrenRecursively(testDescriptor, child -> allResources.addAll(getExclusiveResources(child))); if (!isReadOnly(allResources)) { forceDescendantExecutionModeRecursively(advisor, testDescriptor); } } else { advisor.forceDescendantExecutionMode(testDescriptor, SAME_THREAD); doForChildrenRecursively(testDescriptor, child -> { allResources.addAll(getExclusiveResources(child)); advisor.forceDescendantExecutionMode(child, SAME_THREAD); }); } if (!globalLockDescriptor.equals(testDescriptor) && allResources.contains(GLOBAL_READ_WRITE)) { forceDescendantExecutionModeRecursively(advisor, globalLockDescriptor); advisor.useResourceLock(globalLockDescriptor, globalReadWriteLock); } if (globalLockDescriptor.equals(testDescriptor) && !allResources.contains(GLOBAL_READ_WRITE)) { allResources.add(GLOBAL_READ); } advisor.useResourceLock(testDescriptor, lockManager.getLockForResources(allResources)); } } private void forceDescendantExecutionModeRecursively(NodeExecutionAdvisor advisor, TestDescriptor testDescriptor) { advisor.forceDescendantExecutionMode(testDescriptor, SAME_THREAD); doForChildrenRecursively(testDescriptor, child -> advisor.forceDescendantExecutionMode(child, SAME_THREAD)); } private boolean isReadOnly(Set exclusiveResources) { return exclusiveResources.stream().allMatch( exclusiveResource -> exclusiveResource.getLockMode() == ExclusiveResource.LockMode.READ); } private Set getExclusiveResources(TestDescriptor testDescriptor) { return NodeUtils.asNode(testDescriptor).getExclusiveResources(); } private void doForChildrenRecursively(TestDescriptor parent, Consumer consumer) { parent.getChildren().forEach(child -> { consumer.accept(child); doForChildrenRecursively(child, consumer); }); } } NodeUtils.java000066400000000000000000000014511455764576500357370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import org.junit.platform.engine.TestDescriptor; /** * @since 1.3.1 */ final class NodeUtils { private NodeUtils() { /* no-op */ } @SuppressWarnings("unchecked") static Node asNode(TestDescriptor testDescriptor) { return (testDescriptor instanceof Node ? (Node) testDescriptor : noOpNode); } @SuppressWarnings("rawtypes") private static final Node noOpNode = new Node() { }; } NopLock.java000066400000000000000000000012571455764576500354020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; /** * No-op {@link ResourceLock} implementation. * * @since 1.3 */ class NopLock implements ResourceLock { static final ResourceLock INSTANCE = new NopLock(); private NopLock() { } @Override public ResourceLock acquire() { return this; } @Override public void release() { // nothing to do } } OpenTest4JAwareThrowableCollector.java000066400000000000000000000016111455764576500424650ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.opentest4j.TestAbortedException; /** * Specialization of {@link ThrowableCollector} that treats instances of * {@link TestAbortedException} as aborting. * * @since 1.3 * @see ThrowableCollector */ @API(status = MAINTAINED, since = "1.3") public class OpenTest4JAwareThrowableCollector extends ThrowableCollector { public OpenTest4JAwareThrowableCollector() { super(TestAbortedException.class::isInstance); } } ParallelExecutionConfiguration.java000066400000000000000000000042411455764576500422010ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.util.concurrent.ForkJoinPool; import java.util.function.Predicate; import org.apiguardian.api.API; /** * Configuration to use for parallel test execution. * *

Instances of this class are intended to be used to configure * implementations of {@link HierarchicalTestExecutorService}. Such * implementations may use all of the properties in this class or * only a subset. * * @since 1.3 * @see ForkJoinPoolHierarchicalTestExecutorService * @see ParallelExecutionConfigurationStrategy * @see DefaultParallelExecutionConfigurationStrategy */ @API(status = STABLE, since = "1.10") public interface ParallelExecutionConfiguration { /** * Get the parallelism to be used. * * @see ForkJoinPool#getParallelism() */ int getParallelism(); /** * Get the minimum number of runnable threads to be used. */ int getMinimumRunnable(); /** * Get the maximum thread pool size to be used. */ int getMaxPoolSize(); /** * Get the core thread pool size to be used. */ int getCorePoolSize(); /** * Get the number of seconds for which inactive threads should be kept alive * before terminating them and shrinking the thread pool. */ int getKeepAliveSeconds(); /** * Get the saturate predicate to be used for the execution's {@link ForkJoinPool}. * @return the saturate predicate to be passed to the {@code ForkJoinPool} constructor; may be {@code null} * @since 1.9 * @see ForkJoinPool#ForkJoinPool(int, ForkJoinPool.ForkJoinWorkerThreadFactory, Thread.UncaughtExceptionHandler, * boolean, int, int, int, Predicate, long, TimeUnit) */ @API(status = EXPERIMENTAL, since = "1.9") default Predicate getSaturatePredicate() { return null; } } ParallelExecutionConfigurationStrategy.java000066400000000000000000000017301455764576500437240ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.ConfigurationParameters; /** * A strategy to use for configuring parallel test execution. * * @since 1.3 * @see DefaultParallelExecutionConfigurationStrategy */ @API(status = STABLE, since = "1.10") public interface ParallelExecutionConfigurationStrategy { /** * Create a configuration for parallel test execution based on the supplied * {@link ConfigurationParameters}. */ ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters); } ResourceLock.java000066400000000000000000000021321455764576500364260ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * A lock for a one or more resources. * * @since 1.3 * @see HierarchicalTestExecutorService.TestTask#getResourceLock() */ @API(status = STABLE, since = "1.10") public interface ResourceLock extends AutoCloseable { /** * Acquire this resource lock, potentially blocking. * * @return this lock so it can easily be used in a try-with-resources * statement. * @throws InterruptedException if the calling thread is interrupted * while waiting to acquire this lock */ ResourceLock acquire() throws InterruptedException; /** * Release this resource lock. */ void release(); @Override default void close() { release(); } } SameThreadHierarchicalTestExecutorService.java000066400000000000000000000023401455764576500442430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.concurrent.CompletableFuture.completedFuture; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import java.util.concurrent.Future; import org.apiguardian.api.API; /** * A simple {@linkplain HierarchicalTestExecutorService executor service} that * executes all {@linkplain TestTask test tasks} in the caller's thread. * * @since 1.3 */ @API(status = STABLE, since = "1.10") public class SameThreadHierarchicalTestExecutorService implements HierarchicalTestExecutorService { public SameThreadHierarchicalTestExecutorService() { } @Override public Future submit(TestTask testTask) { testTask.execute(); return completedFuture(null); } @Override public void invokeAll(List tasks) { tasks.forEach(TestTask::execute); } @Override public void close() { // nothing to do } } SingleLock.java000066400000000000000000000022651455764576500360670ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.locks.Lock; /** * @since 1.3 */ class SingleLock implements ResourceLock { private final Lock lock; SingleLock(Lock lock) { this.lock = lock; } // for tests only Lock getLock() { return lock; } @Override public ResourceLock acquire() throws InterruptedException { ForkJoinPool.managedBlock(new SingleLockManagedBlocker()); return this; } @Override public void release() { lock.unlock(); } private class SingleLockManagedBlocker implements ForkJoinPool.ManagedBlocker { private boolean acquired; @Override public boolean block() throws InterruptedException { lock.lockInterruptibly(); acquired = true; return true; } @Override public boolean isReleasable() { return acquired || lock.tryLock(); } } } SingleTestExecutor.java000066400000000000000000000050071455764576500376320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.junit.platform.engine.TestExecutionResult.aborted; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import org.apiguardian.api.API; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestExecutionResult; import org.opentest4j.TestAbortedException; /** * {@code SingleTestExecutor} encapsulates the execution of a single test * wrapped in an {@link Executable}. * * @since 1.0 * @see #executeSafely(Executable) * @deprecated Please use {@link ThrowableCollector#execute} and * {@link ThrowableCollector#toTestExecutionResult} instead. */ @Deprecated @API(status = DEPRECATED, since = "1.2") @SuppressWarnings("missing-explicit-ctor") public class SingleTestExecutor { /** * Functional interface for a single test to be executed by * {@link SingleTestExecutor}. */ @FunctionalInterface public interface Executable { /** * Execute the test. * * @throws TestAbortedException to signal aborted execution * @throws Throwable to signal failure */ void execute() throws TestAbortedException, Throwable; } /** * Execute the supplied {@link Executable} and return a * {@link TestExecutionResult} based on the outcome. * *

If the {@code Executable} throws an unrecoverable exception * — for example, an {@link OutOfMemoryError} — this method will * rethrow it. * * @param executable the test to be executed * @return {@linkplain TestExecutionResult#aborted aborted} if the * {@code Executable} throws a {@link TestAbortedException}; * {@linkplain TestExecutionResult#failed failed} if any other * {@link Throwable} is thrown; and {@linkplain TestExecutionResult#successful * successful} otherwise */ public TestExecutionResult executeSafely(Executable executable) { try { executable.execute(); return successful(); } catch (TestAbortedException e) { return aborted(e); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); return failed(t); } } } ThrowableCollector.java000066400000000000000000000153031455764576500376300ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.engine.TestExecutionResult.aborted; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestExecutionResult; /** * Simple component that can be used to collect one or more instances of * {@link Throwable}. * *

This class distinguishes between {@code Throwables} that abort * and those that fail test execution. The latter take precedence over * the former, i.e. if both types of {@code Throwables} were collected, the ones * that abort execution are reported as * {@linkplain Throwable#addSuppressed(Throwable) suppressed} {@code Throwables} * of the first {@code Throwable} that failed execution. * * @since 1.3 * @see OpenTest4JAwareThrowableCollector */ @API(status = MAINTAINED, since = "1.3") public class ThrowableCollector { private final Predicate abortedExecutionPredicate; private Throwable throwable; /** * Create a new {@code ThrowableCollector} that uses the supplied * {@link Predicate} to determine whether a {@link Throwable} * aborted or failed execution. * * @param abortedExecutionPredicate the predicate used to decide whether a * {@code Throwable} aborted execution; never {@code null}. */ public ThrowableCollector(Predicate abortedExecutionPredicate) { this.abortedExecutionPredicate = Preconditions.notNull(abortedExecutionPredicate, "abortedExecutionPredicate must not be null"); } /** * Execute the supplied {@link Executable} and collect any {@link Throwable} * thrown during the execution. * *

If the {@code Executable} throws an unrecoverable exception * — for example, an {@link OutOfMemoryError} — this method will * rethrow it. * * @param executable the {@code Executable} to execute * @see #assertEmpty() */ public void execute(Executable executable) { try { executable.execute(); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); add(t); } } /** * Add the supplied {@link Throwable} to this {@code ThrowableCollector}. * * @param t the {@code Throwable} to add * @see #execute(Executable) * @see #assertEmpty() */ private void add(Throwable t) { Preconditions.notNull(t, "Throwable must not be null"); if (this.throwable == null) { this.throwable = t; } else if (hasAbortedExecution(this.throwable) && !hasAbortedExecution(t)) { t.addSuppressed(this.throwable); this.throwable = t; } else if (throwable != t) { // Jupiter does not throw the same Throwable from Node.after() anymore but other engines might this.throwable.addSuppressed(t); } } /** * Get the first {@link Throwable} collected by this * {@code ThrowableCollector}. * *

If this collector is not empty, the first collected {@code Throwable} * will be returned with any additional {@code Throwables} * {@linkplain Throwable#addSuppressed(Throwable) suppressed} in the * first {@code Throwable}. * *

If the first collected {@code Throwable} aborted execution * and at least one later collected {@code Throwable} failed * execution, the first failing {@code Throwable} will be returned * with the previous aborting and any additional {@code Throwables} * {@linkplain Throwable#addSuppressed(Throwable) suppressed} inside. * * @return the first collected {@code Throwable} or {@code null} if this * {@code ThrowableCollector} is empty * @see #isEmpty() * @see #assertEmpty() */ public Throwable getThrowable() { return this.throwable; } /** * Determine if this {@code ThrowableCollector} is empty (i.e., * has not collected any {@code Throwables}). */ public boolean isEmpty() { return (this.throwable == null); } /** * Determine if this {@code ThrowableCollector} is not empty (i.e., * has collected at least one {@code Throwable}). */ public boolean isNotEmpty() { return (this.throwable != null); } /** * Assert that this {@code ThrowableCollector} is empty (i.e., * has not collected any {@code Throwables}). * *

If this collector is not empty, the first collected {@code Throwable} * will be thrown with any additional {@code Throwables} * {@linkplain Throwable#addSuppressed(Throwable) suppressed} in the * first {@code Throwable}. Note, however, that the {@code Throwable} * will not be wrapped. Rather, it will be * {@linkplain ExceptionUtils#throwAsUncheckedException masked} * as an unchecked exception. * * @see #getThrowable() * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ public void assertEmpty() { if (!isEmpty()) { ExceptionUtils.throwAsUncheckedException(this.throwable); } } /** * Convert the collected {@link Throwable Throwables} into a {@link TestExecutionResult}. * * @return {@linkplain TestExecutionResult#aborted aborted} if the collected * {@code Throwable} aborted execution; * {@linkplain TestExecutionResult#failed failed} if it failed * execution; and {@linkplain TestExecutionResult#successful successful} * otherwise * @since 1.6 */ @API(status = MAINTAINED, since = "1.6") public TestExecutionResult toTestExecutionResult() { if (isEmpty()) { return successful(); } if (hasAbortedExecution(throwable)) { return aborted(throwable); } return failed(throwable); } private boolean hasAbortedExecution(Throwable t) { return this.abortedExecutionPredicate.test(t); } /** * Functional interface for an executable block of code that may throw a * {@link Throwable}. */ @FunctionalInterface public interface Executable { /** * Execute this executable, potentially throwing a {@link Throwable} * that signals abortion or failure. */ void execute() throws Throwable; } /** * Factory for {@code ThrowableCollector} instances. */ public interface Factory { /** * Create a new instance of a {@code ThrowableCollector}. */ ThrowableCollector create(); } } package-info.java000066400000000000000000000004631455764576500363570ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/** * Support classes and base implementation for any * {@link org.junit.platform.engine.TestEngine} that wishes to organize test suites * hierarchically based on the * {@link org.junit.platform.engine.support.hierarchical.Node} abstraction. */ package org.junit.platform.engine.support.hierarchical; junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/000077500000000000000000000000001455764576500317625ustar00rootroot00000000000000NamespacedHierarchicalStore.java000066400000000000000000000326311455764576500401270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.store; import static java.util.Comparator.comparing; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; import java.util.Comparator; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.support.hierarchical.ThrowableCollector; /** * {@code NamespacedHierarchicalStore} is a hierarchical, namespaced key-value store. * *

Its {@linkplain #close() closing} behavior can be customized by passing a * {@link CloseAction} to the * {@link #NamespacedHierarchicalStore(NamespacedHierarchicalStore, CloseAction)} * constructor. * *

This class is thread-safe. * * @param Namespace type * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") public final class NamespacedHierarchicalStore implements AutoCloseable { private final AtomicInteger insertOrderSequence = new AtomicInteger(); private final ConcurrentMap, StoredValue> storedValues = new ConcurrentHashMap<>(4); private final NamespacedHierarchicalStore parentStore; private final CloseAction closeAction; /** * Create a new store with the supplied parent. * * @param parentStore the parent store to use for lookups; may be {@code null} */ public NamespacedHierarchicalStore(NamespacedHierarchicalStore parentStore) { this(parentStore, null); } /** * Create a new store with the supplied parent and close action. * * @param parentStore the parent store to use for lookups; may be {@code null} * @param closeAction the action to be called for each stored value when this * store is closed; may be {@code null} */ public NamespacedHierarchicalStore(NamespacedHierarchicalStore parentStore, CloseAction closeAction) { this.parentStore = parentStore; this.closeAction = closeAction; } /** * Create a child store with this store as its parent using the same close * action. */ public NamespacedHierarchicalStore newChild() { return new NamespacedHierarchicalStore<>(this, this.closeAction); } /** * If a close action is configured, it will be called with all successfully * stored values in reverse insertion order. * *

Closing a store does not close its parent or any of its children. */ @Override public void close() { if (this.closeAction == null) { return; } ThrowableCollector throwableCollector = new ThrowableCollector(__ -> false); this.storedValues.entrySet().stream() // .map(e -> e.getValue().evaluateSafely(e.getKey())) // .filter(it -> it != null && it.value != null) // .sorted(EvaluatedValue.REVERSE_INSERT_ORDER) // .forEach(it -> throwableCollector.execute(() -> it.close(this.closeAction))); throwableCollector.assertEmpty(); } /** * Get the value stored for the supplied namespace and key in this store or * the parent store, if present. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @return the stored value; may be {@code null} */ public Object get(N namespace, Object key) { StoredValue storedValue = getStoredValue(new CompositeKey<>(namespace, key)); return StoredValue.evaluateIfNotNull(storedValue); } /** * Get the value stored for the supplied namespace and key in this store or * the parent store, if present, and cast it to the supplied required type. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @return the stored value; may be {@code null} * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type */ public T get(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = get(namespace, key); return castToRequiredType(key, value, requiredType); } /** * Get the value stored for the supplied namespace and key in this store or * the parent store, if present, or call the supplied function to compute it. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} but may return {@code null} * @return the stored value; may be {@code null} */ public Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); CompositeKey compositeKey = new CompositeKey<>(namespace, key); StoredValue storedValue = getStoredValue(compositeKey); if (storedValue == null) { storedValue = this.storedValues.computeIfAbsent(compositeKey, __ -> storedValue(new MemoizingSupplier(() -> defaultCreator.apply(key)))); } return storedValue.evaluate(); } /** * Get the value stored for the supplied namespace and key in this store or * the parent store, if present, or call the supplied function to compute it * and, finally, cast it to the supplied required type. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} but may return {@code null} * @param requiredType the required type of the value; never {@code null} * @return the stored value; may be {@code null} * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type */ public V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); return castToRequiredType(key, value, requiredType); } /** * Put the supplied value for the supplied namespace and key into this * store and return the previously associated value in this store. * *

The {@link CloseAction} will not be called for the previously * stored value, if any. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param value the value to store; may be {@code null} * @return the previously stored value; may be {@code null} * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type */ public Object put(N namespace, Object key, Object value) throws NamespacedHierarchicalStoreException { StoredValue oldValue = this.storedValues.put(new CompositeKey<>(namespace, key), storedValue(() -> value)); return StoredValue.evaluateIfNotNull(oldValue); } /** * Remove the value stored for the supplied namespace and key from this * store. * *

The {@link CloseAction} will not be called for the removed * value. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @return the previously stored value; may be {@code null} */ public Object remove(N namespace, Object key) { StoredValue previous = this.storedValues.remove(new CompositeKey<>(namespace, key)); return StoredValue.evaluateIfNotNull(previous); } /** * Remove the value stored for the supplied namespace and key from this * store and cast it to the supplied required type. * *

The {@link CloseAction} will not be called for the removed * value. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @return the previously stored value; may be {@code null} * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type */ public T remove(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = remove(namespace, key); return castToRequiredType(key, value, requiredType); } private StoredValue storedValue(Supplier value) { return new StoredValue(this.insertOrderSequence.getAndIncrement(), value); } private StoredValue getStoredValue(CompositeKey compositeKey) { StoredValue storedValue = this.storedValues.get(compositeKey); if (storedValue != null) { return storedValue; } if (this.parentStore != null) { return this.parentStore.getStoredValue(compositeKey); } return null; } @SuppressWarnings("unchecked") private T castToRequiredType(Object key, Object value, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); if (value == null) { return null; } if (isAssignableTo(value, requiredType)) { if (requiredType.isPrimitive()) { return (T) getWrapperType(requiredType).cast(value); } return requiredType.cast(value); } // else throw new NamespacedHierarchicalStoreException( String.format("Object stored under key [%s] is not of required type [%s]", key, requiredType.getName())); } private static class CompositeKey { private final N namespace; private final Object key; private CompositeKey(N namespace, Object key) { this.namespace = Preconditions.notNull(namespace, "namespace must not be null"); this.key = Preconditions.notNull(key, "key must not be null"); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CompositeKey that = (CompositeKey) o; return this.namespace.equals(that.namespace) && this.key.equals(that.key); } @Override public int hashCode() { return Objects.hash(this.namespace, this.key); } } private static class StoredValue { private final int order; private final Supplier supplier; StoredValue(int order, Supplier supplier) { this.order = order; this.supplier = supplier; } private EvaluatedValue evaluateSafely(CompositeKey compositeKey) { try { return new EvaluatedValue<>(compositeKey, order, evaluate()); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); return null; } } private Object evaluate() { return supplier.get(); } static Object evaluateIfNotNull(StoredValue value) { return value != null ? value.evaluate() : null; } } private static class EvaluatedValue { private static final Comparator> REVERSE_INSERT_ORDER = comparing( (EvaluatedValue it) -> it.order).reversed(); private final CompositeKey compositeKey; private final int order; private final Object value; private EvaluatedValue(CompositeKey compositeKey, int order, Object value) { this.compositeKey = compositeKey; this.order = order; this.value = value; } private void close(CloseAction closeAction) throws Throwable { closeAction.close(this.compositeKey.namespace, this.compositeKey.key, this.value); } } /** * Thread-safe {@link Supplier} that memoizes the result of calling its * delegate and ensures it is called at most once. * *

If the delegate throws an exception, it is stored and rethrown every * time {@link #get()} is called. * * @see StoredValue */ private static class MemoizingSupplier implements Supplier { private static final Object NO_VALUE_SET = new Object(); private final Supplier delegate; private volatile Object value = NO_VALUE_SET; private MemoizingSupplier(Supplier delegate) { this.delegate = delegate; } @Override public Object get() { if (this.value == NO_VALUE_SET) { computeValue(); } if (this.value instanceof Failure) { ExceptionUtils.throwAsUncheckedException(((Failure) this.value).throwable); } return this.value; } private synchronized void computeValue() { try { if (this.value == NO_VALUE_SET) { this.value = this.delegate.get(); } } catch (Throwable t) { this.value = new Failure(t); UnrecoverableExceptions.rethrowIfUnrecoverable(t); } } private static class Failure { private final Throwable throwable; public Failure(Throwable throwable) { this.throwable = throwable; } } } /** * Called for each successfully stored non-null value in the store when a * {@link NamespacedHierarchicalStore} is * {@link NamespacedHierarchicalStore#close() closed}. */ @FunctionalInterface public interface CloseAction { /** * Close the supplied {@code value}. * * @param namespace the namespace; never {@code null} * @param key the key; never {@code null} * @param value the value; never {@code null} */ void close(N namespace, Object key, Object value) throws Throwable; } } NamespacedHierarchicalStoreException.java000066400000000000000000000017571455764576500420130ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.store; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; /** * Exception thrown by failed {@link NamespacedHierarchicalStore} operations. * * @since 5.10 */ @API(status = EXPERIMENTAL, since = "5.10") public class NamespacedHierarchicalStoreException extends JUnitException { private static final long serialVersionUID = 1L; public NamespacedHierarchicalStoreException(String message) { super(message); } @SuppressWarnings("unused") public NamespacedHierarchicalStoreException(String message, Throwable cause) { super(message, cause); } } package-info.java000066400000000000000000000001751455764576500350750ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/** * Reusable data structures for test engines and their extensions. */ package org.junit.platform.engine.support.store; junit5-r5.10.2/junit-platform-engine/src/module/000077500000000000000000000000001455764576500215215ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/module/org.junit.platform.engine/000077500000000000000000000000001455764576500265275ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java000066400000000000000000000022421455764576500316100ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Public API for test engines. * *

Provides the {@linkplain org.junit.platform.engine.TestEngine} interface, test discovery * and execution reporting support. * * @since 1.0 */ module org.junit.platform.engine { requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; requires transitive org.opentest4j; exports org.junit.platform.engine; exports org.junit.platform.engine.discovery; exports org.junit.platform.engine.reporting; // exports org.junit.platform.engine.support; empty package exports org.junit.platform.engine.support.config; exports org.junit.platform.engine.support.descriptor; exports org.junit.platform.engine.support.discovery; exports org.junit.platform.engine.support.filter; exports org.junit.platform.engine.support.hierarchical; exports org.junit.platform.engine.support.store; } junit5-r5.10.2/junit-platform-engine/src/testFixtures/000077500000000000000000000000001455764576500227455ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/000077500000000000000000000000001455764576500236665ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/000077500000000000000000000000001455764576500244555ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500256065ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/000077500000000000000000000000001455764576500274325ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/000077500000000000000000000000001455764576500306775ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/000077500000000000000000000000001455764576500324135ustar00rootroot00000000000000hierarchical/000077500000000000000000000000001455764576500347525ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/supportDemoEngineExecutionContext.java000066400000000000000000000012231455764576500430560ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import org.junit.platform.engine.ExecutionRequest; /** * @since 1.0 */ public class DemoEngineExecutionContext implements EngineExecutionContext { public final ExecutionRequest request; public DemoEngineExecutionContext(ExecutionRequest request) { this.request = request; } } DemoHierarchicalContainerDescriptor.java000066400000000000000000000026441455764576500447100ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.doNotSkip; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; /** * @since 1.0 */ public class DemoHierarchicalContainerDescriptor extends AbstractTestDescriptor implements Node { private final Runnable beforeBlock; public DemoHierarchicalContainerDescriptor(UniqueId uniqueId, String displayName, TestSource source, Runnable beforeBlock) { super(uniqueId, displayName, source); this.beforeBlock = beforeBlock; } @Override public Type getType() { return Type.CONTAINER; } @Override public boolean mayRegisterTests() { return true; } @Override public SkipResult shouldBeSkipped(DemoEngineExecutionContext context) { return doNotSkip(); } @Override public DemoEngineExecutionContext before(DemoEngineExecutionContext context) { if (this.beforeBlock != null) { this.beforeBlock.run(); } return context; } } DemoHierarchicalEngineDescriptor.java000066400000000000000000000027671455764576500442010ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.doNotSkip; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.skip; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; /** * @since 1.0 */ public class DemoHierarchicalEngineDescriptor extends EngineDescriptor implements Node { private String skippedReason; private boolean skipped; private Runnable beforeAllBehavior = () -> { }; public DemoHierarchicalEngineDescriptor(UniqueId uniqueId) { super(uniqueId, uniqueId.getEngineId().orElseThrow()); } public void markSkipped(String reason) { this.skipped = true; this.skippedReason = reason; } public void setBeforeAllBehavior(Runnable beforeAllBehavior) { this.beforeAllBehavior = beforeAllBehavior; } @Override public SkipResult shouldBeSkipped(DemoEngineExecutionContext context) { return skipped ? skip(skippedReason) : doNotSkip(); } @Override public DemoEngineExecutionContext before(DemoEngineExecutionContext context) { beforeAllBehavior.run(); return context; } } DemoHierarchicalTestDescriptor.java000066400000000000000000000041231455764576500436770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.doNotSkip; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.skip; import java.util.function.BiConsumer; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; /** * @since 1.0 */ public class DemoHierarchicalTestDescriptor extends AbstractTestDescriptor implements Node { private final BiConsumer executeBlock; private String skippedReason; private boolean skipped; public DemoHierarchicalTestDescriptor(UniqueId uniqueId, String displayName, BiConsumer executeBlock) { this(uniqueId, displayName, null, executeBlock); } public DemoHierarchicalTestDescriptor(UniqueId uniqueId, String displayName, TestSource source, BiConsumer executeBlock) { super(uniqueId, displayName, source); this.executeBlock = executeBlock; } @Override public Type getType() { return this.executeBlock != null ? Type.TEST : Type.CONTAINER; } public void markSkipped(String reason) { this.skipped = true; this.skippedReason = reason; } @Override public SkipResult shouldBeSkipped(DemoEngineExecutionContext context) { return skipped ? skip(skippedReason) : doNotSkip(); } @Override public DemoEngineExecutionContext execute(DemoEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { if (this.executeBlock != null) { this.executeBlock.accept(context, this); } return context; } } DemoHierarchicalTestEngine.java000066400000000000000000000063321455764576500427720ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.function.BiConsumer; import java.util.function.Function; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; /** * @since 1.0 */ public final class DemoHierarchicalTestEngine extends HierarchicalTestEngine { private final String engineId; private final DemoHierarchicalEngineDescriptor engineDescriptor; public DemoHierarchicalTestEngine() { this("dummy"); } public DemoHierarchicalTestEngine(String engineId) { this.engineId = engineId; this.engineDescriptor = new DemoHierarchicalEngineDescriptor(UniqueId.forEngine(getId())); } @Override public String getId() { return engineId; } public DemoHierarchicalEngineDescriptor getEngineDescriptor() { return engineDescriptor; } public DemoHierarchicalTestDescriptor addTest(String uniqueName, Runnable executeBlock) { return addTest(uniqueName, uniqueName, executeBlock); } public DemoHierarchicalTestDescriptor addTest(String uniqueName, String displayName, Runnable executeBlock) { return addChild(uniqueName, uniqueId -> new DemoHierarchicalTestDescriptor(uniqueId, displayName, (c, t) -> executeBlock.run()), "test"); } public DemoHierarchicalTestDescriptor addTest(String uniqueName, String displayName, BiConsumer executeBlock) { return addChild(uniqueName, uniqueId -> new DemoHierarchicalTestDescriptor(uniqueId, displayName, executeBlock), "test"); } public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, TestSource source) { return addContainer(uniqueName, displayName, source, null); } public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, Runnable beforeBlock) { return addContainer(uniqueName, uniqueName, null, beforeBlock); } public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, TestSource source, Runnable beforeBlock) { return addChild(uniqueName, uniqueId -> new DemoHierarchicalContainerDescriptor(uniqueId, displayName, source, beforeBlock), "container"); } public > T addChild(String uniqueName, Function creator, String segmentType) { var uniqueId = engineDescriptor.getUniqueId().append(segmentType, uniqueName); var child = creator.apply(uniqueId); engineDescriptor.addChild(child); return child; } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { return engineDescriptor; } @Override protected DemoEngineExecutionContext createExecutionContext(ExecutionRequest request) { return new DemoEngineExecutionContext(request); } } junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/000077500000000000000000000000001455764576500305235ustar00rootroot00000000000000TestDescriptorStub.java000066400000000000000000000013771455764576500351330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.fakes; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; /** * @since 1.4 */ public class TestDescriptorStub extends AbstractTestDescriptor { public TestDescriptorStub(UniqueId uniqueId, String displayName) { super(uniqueId, displayName); } @Override public Type getType() { return getChildren().isEmpty() ? Type.TEST : Type.CONTAINER; } } TestEngineSpy.java000066400000000000000000000026161455764576500340550ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.fakes; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; /** * @since 1.4 */ public class TestEngineSpy implements TestEngine { private final String id; public ExecutionRequest requestForExecution; public TestEngineSpy() { this(TestEngineSpy.class.getSimpleName()); } public TestEngineSpy(String id) { this.id = id; } @Override public String getId() { return id; } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { var engineUniqueId = UniqueId.forEngine(id); var engineDescriptor = new TestDescriptorStub(engineUniqueId, id); var testDescriptor = new TestDescriptorStub(engineUniqueId.append("test", "test"), "test"); engineDescriptor.addChild(testDescriptor); return engineDescriptor; } @Override public void execute(ExecutionRequest request) { this.requestForExecution = request; } } TestEngineStub.java000066400000000000000000000021571455764576500342170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.fakes; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; /** * @since 1.4 */ public class TestEngineStub implements TestEngine { private final String id; public TestEngineStub() { this(TestEngineStub.class.getSimpleName()); } public TestEngineStub(String id) { this.id = id; } @Override public String getId() { return this.id; } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { return new TestDescriptorStub(UniqueId.forEngine(getId()), getId()); } @Override public void execute(ExecutionRequest request) { } } junit5-r5.10.2/junit-platform-jfr/000077500000000000000000000000001455764576500167615ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/junit-platform-jfr.gradle.kts000066400000000000000000000011601455764576500244710ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Flight Recorder Support" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } javaLibrary { // --release 8 does not support jdk.jfr even though it was backported configureRelease = false } tasks { compileJava { javaCompiler = project.javaToolchains.compilerFor { languageVersion = JavaLanguageVersion.of(8) } } compileModule { options.release = 11 } } junit5-r5.10.2/junit-platform-jfr/src/000077500000000000000000000000001455764576500175505ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/000077500000000000000000000000001455764576500204745ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/000077500000000000000000000000001455764576500214155ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/000077500000000000000000000000001455764576500222045ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/000077500000000000000000000000001455764576500233355ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500251615ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/jfr/000077500000000000000000000000001455764576500257425ustar00rootroot00000000000000FlightRecordingDiscoveryListener.java000066400000000000000000000061551455764576500352050ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/jfr/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.jfr; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import jdk.jfr.Category; import jdk.jfr.Event; import jdk.jfr.Label; import jdk.jfr.Name; import jdk.jfr.StackTrace; import org.apiguardian.api.API; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * A {@link LauncherDiscoveryListener} that generates Java Flight Recorder * events. * * @since 1.8 * @see JEP 328: Flight Recorder */ @API(status = EXPERIMENTAL, since = "1.8") public class FlightRecordingDiscoveryListener implements LauncherDiscoveryListener { private final AtomicReference launcherDiscoveryEvent = new AtomicReference<>(); private final Map engineDiscoveryEvents = new ConcurrentHashMap<>(); @Override public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { LauncherDiscoveryEvent event = new LauncherDiscoveryEvent(); event.selectors = request.getSelectorsByType(DiscoverySelector.class).size(); event.filters = request.getFiltersByType(DiscoveryFilter.class).size(); event.begin(); launcherDiscoveryEvent.set(event); } @Override public void launcherDiscoveryFinished(LauncherDiscoveryRequest request) { launcherDiscoveryEvent.getAndSet(null).commit(); } @Override public void engineDiscoveryStarted(org.junit.platform.engine.UniqueId engineId) { EngineDiscoveryEvent event = new EngineDiscoveryEvent(); event.uniqueId = engineId.toString(); event.begin(); engineDiscoveryEvents.put(engineId, event); } @Override public void engineDiscoveryFinished(org.junit.platform.engine.UniqueId engineId, EngineDiscoveryResult result) { EngineDiscoveryEvent event = engineDiscoveryEvents.remove(engineId); event.result = result.getStatus().toString(); event.commit(); } @Category({ "JUnit", "Discovery" }) @StackTrace(false) abstract static class DiscoveryEvent extends Event { } @Label("Test Discovery") @Category({ "JUnit", "Discovery" }) @Name("org.junit.LauncherDiscovery") static class LauncherDiscoveryEvent extends DiscoveryEvent { @Label("Number of selectors") int selectors; @Label("Number of filters") int filters; } @Label("Engine Discovery") @Category({ "JUnit", "Discovery" }) @Name("org.junit.EngineDiscovery") static class EngineDiscoveryEvent extends DiscoveryEvent { @UniqueId @Label("Unique Id") String uniqueId; @Label("Result") String result; } } FlightRecordingExecutionListener.java000066400000000000000000000112101455764576500351650ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/jfr/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.jfr; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import jdk.jfr.Category; import jdk.jfr.Event; import jdk.jfr.Label; import jdk.jfr.Name; import jdk.jfr.StackTrace; import org.apiguardian.api.API; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * A {@link TestExecutionListener} that generates Java Flight Recorder * events. * * @since 1.8 * @see JEP 328: Flight Recorder */ @API(status = EXPERIMENTAL, since = "1.8") public class FlightRecordingExecutionListener implements TestExecutionListener { private final AtomicReference testPlanExecutionEvent = new AtomicReference<>(); private final Map testExecutionEvents = new ConcurrentHashMap<>(); @Override public void testPlanExecutionStarted(TestPlan plan) { TestPlanExecutionEvent event = new TestPlanExecutionEvent(); event.containsTests = plan.containsTests(); event.engineNames = plan.getRoots().stream().map(TestIdentifier::getDisplayName).collect( Collectors.joining(", ")); testPlanExecutionEvent.set(event); event.begin(); } @Override public void testPlanExecutionFinished(TestPlan plan) { testPlanExecutionEvent.getAndSet(null).commit(); } @Override public void executionSkipped(TestIdentifier test, String reason) { SkippedTestEvent event = new SkippedTestEvent(); event.initialize(test); event.reason = reason; event.commit(); } @Override public void executionStarted(TestIdentifier test) { TestExecutionEvent event = new TestExecutionEvent(); testExecutionEvents.put(test.getUniqueIdObject(), event); event.initialize(test); event.begin(); } @Override public void executionFinished(TestIdentifier test, TestExecutionResult result) { Optional throwable = result.getThrowable(); TestExecutionEvent event = testExecutionEvents.remove(test.getUniqueIdObject()); event.end(); event.result = result.getStatus().toString(); event.exceptionClass = throwable.map(Throwable::getClass).orElse(null); event.exceptionMessage = throwable.map(Throwable::getMessage).orElse(null); event.commit(); } @Override public void reportingEntryPublished(TestIdentifier test, ReportEntry reportEntry) { for (Map.Entry entry : reportEntry.getKeyValuePairs().entrySet()) { ReportEntryEvent event = new ReportEntryEvent(); event.uniqueId = test.getUniqueId(); event.key = entry.getKey(); event.value = entry.getValue(); event.commit(); } } @Category({ "JUnit", "Execution" }) @StackTrace(false) abstract static class ExecutionEvent extends Event { } @Label("Test Execution") @Name("org.junit.TestPlanExecution") static class TestPlanExecutionEvent extends ExecutionEvent { @Label("Contains Tests") boolean containsTests; @Label("Engine Names") String engineNames; } abstract static class TestEvent extends ExecutionEvent { @UniqueId @Label("Unique Id") String uniqueId; @Label("Display Name") String displayName; @Label("Tags") String tags; @Label("Type") String type; void initialize(TestIdentifier test) { this.uniqueId = test.getUniqueId(); this.displayName = test.getDisplayName(); this.tags = test.getTags().isEmpty() ? null : test.getTags().toString(); this.type = test.getType().name(); } } @Label("Skipped Test") @Name("org.junit.SkippedTest") static class SkippedTestEvent extends TestEvent { @Label("Reason") String reason; } @Label("Test") @Name("org.junit.TestExecution") static class TestExecutionEvent extends TestEvent { @Label("Result") String result; @Label("Exception Class") Class exceptionClass; @Label("Exception Message") String exceptionMessage; } @Label("Report Entry") @Name("org.junit.ReportEntry") static class ReportEntryEvent extends ExecutionEvent { @UniqueId @Label("Unique Id") String uniqueId; @Label("Key") String key; @Label("Value") String value; } } junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/jfr/UniqueId.java000066400000000000000000000013451455764576500303330ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.jfr; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; import jdk.jfr.Relational; @MetadataDefinition @Relational @Name("org.junit.UniqueId") @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface UniqueId { } junit5-r5.10.2/junit-platform-jfr/src/main/java/org/junit/platform/jfr/package-info.java000066400000000000000000000001221455764576500311240ustar00rootroot00000000000000/** * Java Flight Recorder support package. */ package org.junit.platform.jfr; junit5-r5.10.2/junit-platform-jfr/src/main/resources/000077500000000000000000000000001455764576500225065ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/resources/META-INF/000077500000000000000000000000001455764576500236465ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500254715ustar00rootroot00000000000000org.junit.platform.launcher.LauncherDiscoveryListener000066400000000000000000000000701455764576500400320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/resources/META-INF/servicesorg.junit.platform.jfr.FlightRecordingDiscoveryListener org.junit.platform.launcher.TestExecutionListener000066400000000000000000000000701455764576500372040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/main/resources/META-INF/servicesorg.junit.platform.jfr.FlightRecordingExecutionListener junit5-r5.10.2/junit-platform-jfr/src/module/000077500000000000000000000000001455764576500210355ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/module/org.junit.platform.jfr/000077500000000000000000000000001455764576500253575ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-jfr/src/module/org.junit.platform.jfr/module-info.java000066400000000000000000000021761455764576500304460ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Provides Java Flight Recorder events for the JUnit Platform. * *

The Flight Recording Listener module implements a * {@link org.junit.platform.launcher.LauncherDiscoveryListener} and a * {@link org.junit.platform.launcher.TestExecutionListener} that generate Java * Flight Recorder (JFR) events. * * @see JEP 328: Flight Recorder * @since 1.7 */ module org.junit.platform.jfr { requires jdk.jfr; requires static org.apiguardian.api; requires org.junit.platform.engine; requires org.junit.platform.launcher; provides org.junit.platform.launcher.LauncherDiscoveryListener with org.junit.platform.jfr.FlightRecordingDiscoveryListener; provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.jfr.FlightRecordingExecutionListener; } junit5-r5.10.2/junit-platform-launcher/000077500000000000000000000000001455764576500200015ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/junit-platform-launcher.gradle.kts000066400000000000000000000010551455764576500265340ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") `java-test-fixtures` } description = "JUnit Platform Launcher" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformEngine) compileOnlyApi(libs.apiguardian) osgiVerification(projects.junitJupiterEngine) } tasks { jar { bundle { val version = project.version bnd(""" Provide-Capability:\ org.junit.platform.launcher;\ org.junit.platform.launcher='junit-platform-launcher';\ version:Version="${'$'}{version_cleanup;${version}}" """) } } } junit5-r5.10.2/junit-platform-launcher/src/000077500000000000000000000000001455764576500205705ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/000077500000000000000000000000001455764576500215145ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/000077500000000000000000000000001455764576500224355ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/000077500000000000000000000000001455764576500232245ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/000077500000000000000000000000001455764576500243555ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500262015ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/000077500000000000000000000000001455764576500300025ustar00rootroot00000000000000EngineDiscoveryResult.java000066400000000000000000000054021455764576500350630ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.commons.util.ToStringBuilder; /** * {@code EngineDiscoveryResult} encapsulates the result of test discovery by a * {@link org.junit.platform.engine.TestEngine}. * *

A {@code EngineDiscoveryResult} consists of a mandatory * {@link #getStatus() Status} and an optional {@link #getThrowable() Throwable}. * * @since 1.6 */ @API(status = STABLE, since = "1.10") public class EngineDiscoveryResult { /** * Status of test discovery by a * {@link org.junit.platform.engine.TestEngine}. */ public enum Status { /** * Indicates that test discovery was successful. */ SUCCESSFUL, /** * Indicates that test discovery has failed. */ FAILED } private static final EngineDiscoveryResult SUCCESSFUL_RESULT = new EngineDiscoveryResult(Status.SUCCESSFUL, null); /** * Create a {@code EngineDiscoveryResult} for a successful test * discovery. * @return the {@code EngineDiscoveryResult}; never {@code null} */ public static EngineDiscoveryResult successful() { return SUCCESSFUL_RESULT; } /** * Create a {@code EngineDiscoveryResult} for a failed test * discovery. * * @param throwable the throwable that caused the failed discovery; may be * {@code null} * @return the {@code EngineDiscoveryResult}; never {@code null} */ public static EngineDiscoveryResult failed(Throwable throwable) { return new EngineDiscoveryResult(Status.FAILED, throwable); } private final Status status; private final Throwable throwable; private EngineDiscoveryResult(Status status, Throwable throwable) { this.status = status; this.throwable = throwable; } /** * Get the {@linkplain Status status} of this result. * * @return the status; never {@code null} */ public Status getStatus() { return status; } /** * Get the throwable that caused this result, if available. * * @return an {@code Optional} containing the throwable; never {@code null} * but potentially empty */ public Optional getThrowable() { return Optional.ofNullable(throwable); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("status", status) .append("throwable", throwable) .toString(); // @formatter:on } } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java000066400000000000000000000127121455764576500332230ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.FilterResult.includedIf; import java.util.Arrays; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.Filter; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestEngine; /** * An {@code EngineFilter} is applied to all {@link TestEngine TestEngines} * before they are used. * *

Warning: be cautious when registering multiple competing * {@link #includeEngines include} {@code EngineFilters} or multiple competing * {@link #excludeEngines exclude} {@code EngineFilters} for the same discovery * request since doing so will likely lead to undesirable results (i.e., zero * engines being active). * * @since 1.0 * @see #includeEngines(String...) * @see #excludeEngines(String...) * @see LauncherDiscoveryRequest */ @API(status = STABLE, since = "1.0") public class EngineFilter implements Filter { /** * Create a new include {@code EngineFilter} based on the * supplied engine IDs. * *

Only {@code TestEngines} with matching engine IDs will be * included within the test discovery and execution. * * @param engineIds the list of engine IDs to match against; never {@code null} * or empty; individual IDs must also not be null or blank * @see #includeEngines(String...) */ public static EngineFilter includeEngines(String... engineIds) { return includeEngines(Arrays.asList(engineIds)); } /** * Create a new include {@code EngineFilter} based on the * supplied engine IDs. * *

Only {@code TestEngines} with matching engine IDs will be * included within the test discovery and execution. * * @param engineIds the list of engine IDs to match against; never {@code null} * or empty; individual IDs must also not be null or blank * @see #includeEngines(String...) */ public static EngineFilter includeEngines(List engineIds) { return new EngineFilter(engineIds, Type.INCLUDE); } /** * Create a new exclude {@code EngineFilter} based on the * supplied engine IDs. * *

{@code TestEngines} with matching engine IDs will be * excluded from test discovery and execution. * * @param engineIds the list of engine IDs to match against; never {@code null} * or empty; individual IDs must also not be null or blank * @see #excludeEngines(List) */ public static EngineFilter excludeEngines(String... engineIds) { return excludeEngines(Arrays.asList(engineIds)); } /** * Create a new exclude {@code EngineFilter} based on the * supplied engine IDs. * *

{@code TestEngines} with matching engine IDs will be * excluded from test discovery and execution. * * @param engineIds the list of engine IDs to match against; never {@code null} * or empty; individual IDs must also not be null or blank * @see #includeEngines(String...) */ public static EngineFilter excludeEngines(List engineIds) { return new EngineFilter(engineIds, Type.EXCLUDE); } private final List engineIds; private final Type type; private EngineFilter(List engineIds, Type type) { this.engineIds = validateAndTrim(engineIds); this.type = type; } @API(status = INTERNAL, since = "1.9") public List getEngineIds() { return engineIds; } @API(status = INTERNAL, since = "1.9") public boolean isIncludeFilter() { return type == Type.INCLUDE; } @Override public FilterResult apply(TestEngine testEngine) { Preconditions.notNull(testEngine, "TestEngine must not be null"); String engineId = testEngine.getId(); Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); if (this.type == Type.INCLUDE) { return includedIf(this.engineIds.stream().anyMatch(engineId::equals), // () -> String.format("Engine ID [%s] is in included list [%s]", engineId, this.engineIds), // () -> String.format("Engine ID [%s] is not in included list [%s]", engineId, this.engineIds)); } else { return includedIf(this.engineIds.stream().noneMatch(engineId::equals), // () -> String.format("Engine ID [%s] is not in excluded list [%s]", engineId, this.engineIds), // () -> String.format("Engine ID [%s] is in excluded list [%s]", engineId, this.engineIds)); } } @Override public String toString() { return String.format("%s that %s engines with IDs %s", getClass().getSimpleName(), this.type.verb, this.engineIds); } private static List validateAndTrim(List engineIds) { Preconditions.notEmpty(engineIds, "engine ID list must not be null or empty"); // @formatter:off return engineIds.stream() .map(id -> Preconditions.notBlank(id, "engine ID must not be null or blank").trim()) .distinct() .collect(toList()); // @formatter:on } private enum Type { INCLUDE("includes"), EXCLUDE("excludes"); private final String verb; Type(String verb) { this.verb = verb; } } } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java000066400000000000000000000125551455764576500324160ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * The {@code Launcher} API is the main entry point for client code that * wishes to discover and execute tests using one or more * {@linkplain org.junit.platform.engine.TestEngine test engines}. * *

Implementations of this interface are responsible for determining * the set of test engines to delegate to at runtime and for ensuring that * each test engine has an * {@linkplain org.junit.platform.engine.TestEngine#getId ID} that is unique * among the registered test engines. For example, the default implementation * returned by {@link org.junit.platform.launcher.core.LauncherFactory#create} * dynamically discovers test engines via Java's {@link java.util.ServiceLoader * ServiceLoader} mechanism. * *

Test discovery and execution require a {@link LauncherDiscoveryRequest} * that is passed to all registered engines. Each engine decides which tests it * can discover and execute according to the supplied request. * *

Prior to executing tests, clients of this interface should * {@linkplain #registerTestExecutionListeners register} one or more * {@link TestExecutionListener} instances in order to get feedback about the * progress and results of test execution. Listeners will be notified of events * in the order in which they were registered. The default implementation * returned by {@link org.junit.platform.launcher.core.LauncherFactory#create} * dynamically discovers test execution listeners via Java's * {@link java.util.ServiceLoader ServiceLoader} mechanism. * * @since 1.0 * @see LauncherDiscoveryRequest * @see TestPlan * @see TestExecutionListener * @see org.junit.platform.launcher.core.LauncherFactory * @see org.junit.platform.engine.TestEngine */ @API(status = STABLE, since = "1.0") public interface Launcher { /** * Register one or more listeners for test discovery. * * @param listeners the listeners to be notified of test discovery events; * never {@code null} or empty */ @API(status = STABLE, since = "1.10") void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners); /** * Register one or more listeners for test execution. * * @param listeners the listeners to be notified of test execution events; * never {@code null} or empty */ void registerTestExecutionListeners(TestExecutionListener... listeners); /** * Discover tests and build a {@link TestPlan} according to the supplied * {@link LauncherDiscoveryRequest} by querying all registered engines and * collecting their results. * * @apiNote This method may be called to generate a preview of the test * tree. The resulting {@link TestPlan} is unmodifiable and may be passed to * {@link #execute(TestPlan, TestExecutionListener...)} for execution at * most once. * * @param launcherDiscoveryRequest the launcher discovery request; never * {@code null} * @return an unmodifiable {@code TestPlan} that contains all resolved * {@linkplain TestIdentifier identifiers} from all registered engines */ TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest); /** * Execute a {@link TestPlan} which is built according to the supplied * {@link LauncherDiscoveryRequest} by querying all registered engines and * collecting their results, and notify * {@linkplain #registerTestExecutionListeners registered listeners} about * the progress and results of the execution. * *

Supplied test execution listeners are registered in addition to already * registered listeners but only for the supplied launcher discovery request. * * @apiNote Calling this method will cause test discovery to be executed for * all registered engines. If the same {@link LauncherDiscoveryRequest} was * previously passed to {@link #discover(LauncherDiscoveryRequest)}, you * should instead call {@link #execute(TestPlan, TestExecutionListener...)} * and pass the already acquired {@link TestPlan} to avoid the potential * performance degradation (e.g., classpath scanning) of running test * discovery twice. * * @param launcherDiscoveryRequest the launcher discovery request; never {@code null} * @param listeners additional test execution listeners; never {@code null} */ void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners); /** * Execute the supplied {@link TestPlan} and notify * {@linkplain #registerTestExecutionListeners registered listeners} about * the progress and results of the execution. * *

Supplied test execution listeners are registered in addition to * already registered listeners but only for the execution of the supplied * test plan. * * @apiNote The supplied {@link TestPlan} must not have been executed * previously. * * @param testPlan the test plan to execute; never {@code null} * @param listeners additional test execution listeners; never {@code null} * @since 1.4 */ @API(status = STABLE, since = "1.4") void execute(TestPlan testPlan, TestExecutionListener... listeners); } LauncherConstants.java000066400000000000000000000154211455764576500342270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.engine.reporting.ReportEntry; /** * Collection of constants related to {@link Launcher}. * * @since 1.3 * @see org.junit.platform.engine.ConfigurationParameters */ @API(status = STABLE, since = "1.7") public class LauncherConstants { /** * Property name used to enable capturing output to {@link System#out}: * {@value} * *

By default, output to {@link System#out} is not captured. * *

If enabled, the JUnit Platform captures the corresponding output and * publishes it as a {@link ReportEntry} using the * {@value #STDOUT_REPORT_ENTRY_KEY} key immediately before reporting the * test identifier as finished. * * @see #STDOUT_REPORT_ENTRY_KEY * @see ReportEntry * @see TestExecutionListener#reportingEntryPublished(TestIdentifier, ReportEntry) */ public static final String CAPTURE_STDOUT_PROPERTY_NAME = "junit.platform.output.capture.stdout"; /** * Property name used to enable capturing output to {@link System#err}: * {@value} * *

By default, output to {@link System#err} is not captured. * *

If enabled, the JUnit Platform captures the corresponding output and * publishes it as a {@link ReportEntry} using the * {@value #STDERR_REPORT_ENTRY_KEY} key immediately before reporting the * test identifier as finished. * * @see #STDERR_REPORT_ENTRY_KEY * @see ReportEntry * @see TestExecutionListener#reportingEntryPublished(TestIdentifier, ReportEntry) */ public static final String CAPTURE_STDERR_PROPERTY_NAME = "junit.platform.output.capture.stderr"; /** * Property name used to configure the maximum number of bytes for buffering * to use per thread and output type if output capturing is enabled: * {@value} * *

Value must be an integer; defaults to {@value #CAPTURE_MAX_BUFFER_DEFAULT}. * * @see #CAPTURE_MAX_BUFFER_DEFAULT */ public static final String CAPTURE_MAX_BUFFER_PROPERTY_NAME = "junit.platform.output.capture.maxBuffer"; /** * Default maximum number of bytes for buffering to use per thread and * output type if output capturing is enabled. * * @see #CAPTURE_MAX_BUFFER_PROPERTY_NAME */ public static final int CAPTURE_MAX_BUFFER_DEFAULT = 4 * 1024 * 1024; /** * Key used to publish captured output to {@link System#out} as part of a * {@link ReportEntry}: {@value} */ public static final String STDOUT_REPORT_ENTRY_KEY = "stdout"; /** * Key used to publish captured output to {@link System#err} as part of a * {@link ReportEntry}: {@value} */ public static final String STDERR_REPORT_ENTRY_KEY = "stderr"; /** * Property name used to provide patterns for deactivating listeners registered * via the {@link java.util.ServiceLoader ServiceLoader} mechanism: {@value} * *

Pattern Matching Syntax

* *

If the property value consists solely of an asterisk ({@code *}), all * listeners will be deactivated. Otherwise, the property value will be treated * as a comma-separated list of patterns where each individual pattern will be * matched against the fully qualified class name (FQCN) of each registered * listener. Any dot ({@code .}) in a pattern will match against a dot ({@code .}) * or a dollar sign ({@code $}) in a FQCN. Any asterisk ({@code *}) will match * against one or more characters in a FQCN. All other characters in a pattern * will be matched one-to-one against a FQCN. * *

Examples

* *
    *
  • {@code *}: deactivates all listeners. *
  • {@code org.junit.*}: deactivates every listener under the {@code org.junit} * base package and any of its subpackages. *
  • {@code *.MyListener}: deactivates every listener whose simple class name is * exactly {@code MyListener}. *
  • {@code *System*, *Dev*}: deactivates every listener whose FQCN contains * {@code System} or {@code Dev}. *
  • {@code org.example.MyListener, org.example.TheirListener}: deactivates * listeners whose FQCN is exactly {@code org.example.MyListener} or * {@code org.example.TheirListener}. *
* * @see #DEACTIVATE_ALL_LISTENERS_PATTERN * @see org.junit.platform.launcher.TestExecutionListener */ public static final String DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME = "junit.platform.execution.listeners.deactivate"; /** * Wildcard pattern which signals that all listeners registered via the * {@link java.util.ServiceLoader ServiceLoader} mechanism should be deactivated: * {@value} * * @see #DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME * @see org.junit.platform.launcher.TestExecutionListener */ public static final String DEACTIVATE_ALL_LISTENERS_PATTERN = ClassNamePatternFilterUtils.DEACTIVATE_ALL_PATTERN; /** * Property name used to enable support for * {@link LauncherInterceptor} instances to be registered via the * {@link java.util.ServiceLoader ServiceLoader} mechanism: {@value} * *

By default, interceptor registration is disabled. * * @see LauncherInterceptor */ @API(status = EXPERIMENTAL, since = "1.10") public static final String ENABLE_LAUNCHER_INTERCEPTORS = "junit.platform.launcher.interceptors.enabled"; /** * Property name used to enable dry-run mode for test execution. * *

When dry-run mode is enabled, no tests will be executed. Instead, all * registered {@link TestExecutionListener TestExecutionListeners} will * receive events for all test descriptors that are part of the discovered * {@link TestPlan}. All containers will be reported as successful and all * tests as skipped. This can be useful to test changes in the configuration * of a build or to verify a listener is called as expected without having * to wait for all tests to be executed. * *

Value must be either {@code true} or {@code false}; defaults to {@code false}. */ @API(status = EXPERIMENTAL, since = "1.10") public static final String DRY_RUN_PROPERTY_NAME = "junit.platform.execution.dryRun.enabled"; /** * Property name used to enable or disable stack trace pruning. * *

By default, stack trace pruning is enabled. * * @see org.junit.platform.launcher.core.EngineExecutionOrchestrator */ @API(status = EXPERIMENTAL, since = "1.10") public static final String STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME = "junit.platform.stacktrace.pruning.enabled"; private LauncherConstants() { /* no-op */ } } LauncherDiscoveryListener.java000066400000000000000000000060221455764576500357250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.EngineDiscoveryListener; import org.junit.platform.engine.UniqueId; /** * Register a concrete implementation of this interface with a * {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} or * {@link Launcher} to be notified of events that occur during test discovery. * *

All methods in this interface have empty default implementations. * Concrete implementations may therefore override one or more of these methods * to be notified of the selected events. * *

JUnit provides default implementations that are created via the factory * methods in * {@link org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners}. * *

The methods declared in this interface are called by the {@link Launcher} * created via the {@link org.junit.platform.launcher.core.LauncherFactory} * during test discovery. * * @since 1.6 * @see org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners * @see LauncherDiscoveryRequest#getDiscoveryListener() * @see org.junit.platform.launcher.core.LauncherConfig.Builder#addLauncherDiscoveryListeners */ @API(status = EXPERIMENTAL, since = "1.6") public interface LauncherDiscoveryListener extends EngineDiscoveryListener { /** * No-op implementation of {@code LauncherDiscoveryListener} */ LauncherDiscoveryListener NOOP = new LauncherDiscoveryListener() { }; /** * Called when test discovery is about to be started. * * @param request the request for which discovery is being started * @since 1.8 */ @API(status = STABLE, since = "1.10") default void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { } /** * Called when test discovery has finished. * * @param request the request for which discovery has finished * @since 1.8 */ @API(status = STABLE, since = "1.10") default void launcherDiscoveryFinished(LauncherDiscoveryRequest request) { } /** * Called when test discovery is about to be started for an engine. * * @param engineId the unique ID of the engine descriptor */ default void engineDiscoveryStarted(UniqueId engineId) { } /** * Called when test discovery has finished for an engine. * *

Exceptions thrown by implementations of this method will cause the * complete test discovery to be aborted. * * @param engineId the unique ID of the engine descriptor * @param result the discovery result of the supplied engine * @see EngineDiscoveryResult */ default void engineDiscoveryFinished(UniqueId engineId, EngineDiscoveryResult result) { } } LauncherDiscoveryRequest.java000066400000000000000000000071641455764576500356000ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; /** * {@code LauncherDiscoveryRequest} extends the {@link EngineDiscoveryRequest} API * with additional filters that are applied by the {@link Launcher} itself. * *

Specifically, a {@code LauncherDiscoveryRequest} contains the following. * *

    *
  • {@linkplain EngineFilter Engine Filters}: filters that are applied before * each {@code TestEngine} is executed. All of them have to include an engine for it * to contribute to the test plan.
  • *
  • {@linkplain ConfigurationParameters Configuration Parameters}: configuration * parameters that can be used to influence the discovery process
  • *
  • {@linkplain DiscoverySelector Discovery Selectors}: components that select * resources that a {@code TestEngine} can use to discover tests
  • *
  • {@linkplain DiscoveryFilter Discovery Filters}: filters that should be applied * by {@code TestEngines} during test discovery. All of them have to include a * resource for it to end up in the test plan.
  • *
  • {@linkplain PostDiscoveryFilter Post-Discovery Filters}: filters that will be * applied by the {@code Launcher} after {@code TestEngines} have performed test * discovery. All of them have to include a {@code TestDescriptor} for it to end up * in the test plan.
  • *
* * @since 1.0 * @see org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder * @see EngineDiscoveryRequest * @see EngineFilter * @see ConfigurationParameters * @see DiscoverySelector * @see DiscoveryFilter * @see PostDiscoveryFilter * @see #getEngineFilters() * @see #getPostDiscoveryFilters() */ @API(status = STABLE, since = "1.0") public interface LauncherDiscoveryRequest extends EngineDiscoveryRequest { /** * Get the {@code EngineFilters} for this request. * *

The returned filters are to be combined using AND semantics, i.e. all * of them have to include an engine for it to contribute to the test plan. * * @return the list of {@code EngineFilters} for this request; never * {@code null} but potentially empty */ List getEngineFilters(); /** * Get the {@code PostDiscoveryFilters} for this request. * *

The returned filters are to be combined using AND semantics, i.e. all * of them have to include a {@code TestDescriptor} for it to end up in the * test plan. * * @return the list of {@code PostDiscoveryFilters} for this request; never * {@code null} but potentially empty */ List getPostDiscoveryFilters(); /** * Get the {@link LauncherDiscoveryListener} for this request. * *

The default implementation returns a no-op listener that ignores all * calls so that engines that call this methods can be used with an earlier * version of the JUnit Platform that did not yet include it. * * @return the discovery listener; never {@code null} * @since 1.6 */ @API(status = STABLE, since = "1.10") @Override default LauncherDiscoveryListener getDiscoveryListener() { return LauncherDiscoveryListener.NOOP; } } LauncherInterceptor.java000066400000000000000000000052401455764576500345470ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; /** * Interceptor for test discovery and execution by a {@link Launcher} in the * context of a {@link LauncherSession}. * *

Interceptors are instantiated once per {@link LauncherSession} and closed * after the session is closed. They can * {@linkplain #intercept(Invocation) intercept} the following invocations: *

    *
  • * creation of {@link LauncherSessionListener} instances registered via the * {@link java.util.ServiceLoader ServiceLoader} mechanism *
  • *
  • * creation of {@link Launcher} instances *
  • *
  • * calls to {@link Launcher#discover(LauncherDiscoveryRequest)}, * {@link Launcher#execute(TestPlan, TestExecutionListener...)}, and * {@link Launcher#execute(LauncherDiscoveryRequest, TestExecutionListener...)} *
  • *
* *

Implementations of this interface can be registered via the * {@link java.util.ServiceLoader ServiceLoader} mechanism by additionally * setting the {@value LauncherConstants#ENABLE_LAUNCHER_INTERCEPTORS} * configuration parameter to {@code true}. * *

A typical use case is to create a custom {@link ClassLoader} in the * constructor of the implementing class, replace the * {@link Thread#setContextClassLoader(ClassLoader) contextClassLoader} of the * current thread while {@link #intercept(Invocation) intercepting} invocations, * and close the custom {@code ClassLoader} in {@link #close()} * * @since 1.10 * @see Launcher * @see LauncherSession * @see LauncherConstants#ENABLE_LAUNCHER_INTERCEPTORS */ @API(status = EXPERIMENTAL, since = "1.10") public interface LauncherInterceptor { /** * Intercept the supplied invocation. * *

Implementations must call {@link Invocation#proceed()} exactly once. * * @param invocation the intercepted invocation; never {@code null} * @return the result of the invocation */ T intercept(Invocation invocation); /** * Closes this interceptor. * *

Any resources held by this interceptor should be released by this * method. */ void close(); /** * An invocation that can be intercepted. * *

This interface is not intended to be implemented by clients. */ interface Invocation { T proceed(); } } LauncherSession.java000066400000000000000000000026701455764576500337000ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.launcher.core.LauncherFactory; /** * The {@code LauncherSession} API is the main entry point for client code that * wishes to repeatedly discover and execute tests using one * or more {@linkplain org.junit.platform.engine.TestEngine test engines}. * * @since 1.8 * @see Launcher * @see LauncherSessionListener * @see LauncherFactory */ @API(status = STABLE, since = "1.10") public interface LauncherSession extends AutoCloseable { /** * Get the {@link Launcher} associated with this session. * *

Any call to the launcher returned by this method after the session has * been closed will throw an exception. */ Launcher getLauncher(); /** * Close this session and notify all registered * {@link LauncherSessionListener LauncherSessionListeners}. * * @apiNote The behavior of calling this method concurrently with any call * to the {@link Launcher} returned by {@link #getLauncher()} is currently * undefined. */ @Override void close(); } LauncherSessionListener.java000066400000000000000000000037741455764576500354140ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.launcher.core.LauncherConfig; import org.junit.platform.launcher.core.LauncherFactory; /** * Register an implementation of this interface to be notified when a * {@link LauncherSession} is opened and closed. * *

A {@code LauncherSessionListener} can be registered programmatically with * the {@link LauncherConfig.Builder#addLauncherSessionListeners LauncherConfig} * passed to the * {@link LauncherFactory#openSession(LauncherConfig) LauncherFactory} or * automatically via Java's {@link java.util.ServiceLoader ServiceLoader} * mechanism. * *

All methods in this class have empty default implementations. * Subclasses may therefore override one or more of these methods to be notified * of the selected events. * *

The methods declared in this interface are called by the {@link Launcher} * or {@link LauncherSession} created via the {@link LauncherFactory}. * * @since 1.8 * @see LauncherSession * @see LauncherConfig.Builder#addLauncherSessionListeners * @see LauncherFactory */ @API(status = STABLE, since = "1.10") public interface LauncherSessionListener { /** * No-op implementation of {@code LauncherSessionListener} */ LauncherSessionListener NOOP = new LauncherSessionListener() { }; /** * Called when a launcher session was opened. * * @param session the opened session */ default void launcherSessionOpened(LauncherSession session) { } /** * Called when a launcher session was closed. * * @param session the closed session */ default void launcherSessionClosed(LauncherSession session) { } } PostDiscoveryFilter.java000066400000000000000000000022041455764576500345470ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.Filter; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; /** * A {@code PostDiscoveryFilter} is applied to {@link TestDescriptor TestDescriptors} * after test discovery. * *

A {@code PostDiscoveryFilter} must not modify the * {@link TestDescriptor TestDescriptors} it is applied to in any way. * *

{@link TestEngine TestEngines} must not apply * {@code PostDiscoveryFilters} during the test discovery phase. * * @since 1.0 * @see LauncherDiscoveryRequest * @see TestEngine */ @API(status = STABLE, since = "1.0") public interface PostDiscoveryFilter extends Filter { } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java000066400000000000000000000171011455764576500325260ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.util.List; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestTag; import org.junit.platform.launcher.tagexpression.TagExpression; /** * Factory methods for creating {@link PostDiscoveryFilter PostDiscoveryFilters} * based on included and excluded tags or tag expressions. * *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and), and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the * JUnit 5 User Guide * for usage examples. * *

Please note that a tag name is a valid tag expression. Thus, wherever a tag * expression can be used, a single tag name can also be used. * * @since 1.0 * @see #includeTags(String...) * @see #excludeTags(String...) * @see TestTag */ @API(status = STABLE, since = "1.0") public final class TagFilter { private TagFilter() { /* no-op */ } /** * Create an include filter based on the supplied tag expressions. * *

Containers and tests will only be executed if their tags match at * least one of the supplied included tag expressions. * * @param tagExpressions the included tag expressions; never {@code null} or * empty * @throws PreconditionViolationException if the supplied tag expressions * array is {@code null} or empty, or if any individual tag expression is * not syntactically valid * @see #includeTags(List) * @see TestTag#isValid(String) */ public static PostDiscoveryFilter includeTags(String... tagExpressions) throws PreconditionViolationException { Preconditions.notNull(tagExpressions, "array of tag expressions must not be null"); return includeTags(asList(tagExpressions)); } /** * Create an include filter based on the supplied tag expressions. * *

Containers and tests will only be executed if their tags match at * least one of the supplied included tag expressions. * * @param tagExpressions the included tag expressions; never {@code null} or * empty * @throws PreconditionViolationException if the supplied tag expressions * array is {@code null} or empty, or if any individual tag expression is * not syntactically valid * @see #includeTags(String...) * @see TestTag#isValid(String) */ public static PostDiscoveryFilter includeTags(List tagExpressions) throws PreconditionViolationException { Preconditions.notEmpty(tagExpressions, "list of tag expressions must not be null or empty"); return includeMatching(tagExpressions); } /** * Create an exclude filter based on the supplied tag expressions. * *

Containers and tests will only be executed if their tags do * not match any of the supplied excluded tag expressions. * * @param tagExpressions the excluded tag expressions; never {@code null} or * empty * @throws PreconditionViolationException if the supplied tag expressions * array is {@code null} or empty, or if any individual tag expression is * not syntactically valid * @see #excludeTags(List) * @see TestTag#isValid(String) */ public static PostDiscoveryFilter excludeTags(String... tagExpressions) throws PreconditionViolationException { Preconditions.notNull(tagExpressions, "array of tag expressions must not be null"); return excludeTags(asList(tagExpressions)); } /** * Create an exclude filter based on the supplied tag expressions. * *

Containers and tests will only be executed if their tags do * not match any of the supplied excluded tag expressions. * * @param tagExpressions the excluded tag expressions; never {@code null} or * empty * @throws PreconditionViolationException if the supplied tag expressions * array is {@code null} or empty, or if any individual tag expression is * not syntactically valid * @see #excludeTags(String...) * @see TestTag#isValid(String) */ public static PostDiscoveryFilter excludeTags(List tagExpressions) throws PreconditionViolationException { Preconditions.notEmpty(tagExpressions, "list of tag expressions must not be null or empty"); return excludeMatching(tagExpressions); } private static PostDiscoveryFilter includeMatching(List tagExpressions) { Supplier inclusionReason = () -> inclusionReasonExpressionSatisfy(tagExpressions); Supplier exclusionReason = () -> exclusionReasonExpressionNotSatisfy(tagExpressions); List parsedTagExpressions = parseAll(tagExpressions); return descriptor -> { Set tags = descriptor.getTags(); boolean included = parsedTagExpressions.stream().anyMatch(expression -> expression.evaluate(tags)); return FilterResult.includedIf(included, inclusionReason, exclusionReason); }; } private static String inclusionReasonExpressionSatisfy(List tagExpressions) { return String.format("included because tags match expression(s): [%s]", formatToString(tagExpressions)); } private static String exclusionReasonExpressionNotSatisfy(List tagExpressions) { return String.format("excluded because tags do not match tag expression(s): [%s]", formatToString(tagExpressions)); } private static PostDiscoveryFilter excludeMatching(List tagExpressions) { Supplier inclusionReason = () -> inclusionReasonExpressionNotSatisfy(tagExpressions); Supplier exclusionReason = () -> exclusionReasonExpressionSatisfy(tagExpressions); List parsedTagExpressions = parseAll(tagExpressions); return descriptor -> { Set tags = descriptor.getTags(); boolean included = parsedTagExpressions.stream().noneMatch(expression -> expression.evaluate(tags)); return FilterResult.includedIf(included, inclusionReason, exclusionReason); }; } private static String inclusionReasonExpressionNotSatisfy(List tagExpressions) { return String.format("included because tags do not match expression(s): [%s]", formatToString(tagExpressions)); } private static String exclusionReasonExpressionSatisfy(List tagExpressions) { return String.format("excluded because tags match tag expression(s): [%s]", formatToString(tagExpressions)); } private static String formatToString(List tagExpressions) { return tagExpressions.stream().map(String::trim).sorted().collect(Collectors.joining(",")); } private static List parseAll(List tagExpressions) { return tagExpressions.stream().map(TagFilter::parse).collect(toUnmodifiableList()); } private static TagExpression parse(String tagExpression) { return TagExpression.parseFrom(tagExpression).tagExpressionOrThrow( message -> new PreconditionViolationException( "Unable to parse tag expression \"" + tagExpression + "\": " + message)); } } TestExecutionListener.java000066400000000000000000000156521455764576500351100ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.engine.reporting.ReportEntry; /** * Register a concrete implementation of this interface with a {@link Launcher} * to be notified of events that occur during test execution. * *

All methods in this interface have empty default implementations. * Concrete implementations may therefore override one or more of these methods * to be notified of the selected events. * *

All {@code TestExecutionListener} methods are called sequentially. Methods * for start events are called in registration order while methods for finish * events are called in reverse order. Test case execution won't start before * all {@link #executionStarted(TestIdentifier)} calls have returned. * *

JUnit provides two example implementations. * *

    *
  • {@link org.junit.platform.launcher.listeners.LoggingListener}
  • *
  • {@link org.junit.platform.launcher.listeners.SummaryGeneratingListener}
  • *
* *

Contrary to JUnit 4, {@linkplain org.junit.platform.engine.TestEngine test engines} * are supposed to report events not only for {@linkplain TestIdentifier identifiers} * that represent executable leaves in the {@linkplain TestPlan test plan} but also * for all intermediate containers. However, while both the JUnit Vintage and JUnit * Jupiter engines comply with this contract, there is no way to guarantee this for * third-party engines. * *

As of JUnit Platform 1.8, a {@code TestExecutionListener} can access * {@linkplain org.junit.platform.engine.ConfigurationParameters configuration * parameters} via the {@link TestPlan#getConfigurationParameters() * getConfigurationParameters()} method in the {@code TestPlan} supplied to * {@link #testPlanExecutionStarted(TestPlan)} and * {@link #testPlanExecutionFinished(TestPlan)}. * *

Note on concurrency: {@link #testPlanExecutionStarted(TestPlan)} and * {@link #testPlanExecutionFinished(TestPlan)} are always called from the same * thread. It is safe to assume that there is at most one {@code TestPlan} * instance at a time. All other methods could be called from different threads * concurrently in case one or multiple test engines execute tests in parallel. * * @since 1.0 * @see Launcher * @see TestPlan * @see TestIdentifier */ @API(status = STABLE, since = "1.0") public interface TestExecutionListener { /** * Called when the execution of the {@link TestPlan} has started, * before any test has been executed. * *

Called from the same thread as {@link #testPlanExecutionFinished(TestPlan)}. * * @param testPlan describes the tree of tests about to be executed */ default void testPlanExecutionStarted(TestPlan testPlan) { } /** * Called when the execution of the {@link TestPlan} has finished, * after all tests have been executed. * *

Called from the same thread as {@link #testPlanExecutionStarted(TestPlan)}. * * @param testPlan describes the tree of tests that have been executed */ default void testPlanExecutionFinished(TestPlan testPlan) { } /** * Called when a new, dynamic {@link TestIdentifier} has been registered. * *

A dynamic test is a test that is not known a-priori and * therefore not contained in the original {@link TestPlan}. * * @param testIdentifier the identifier of the newly registered test * or container */ default void dynamicTestRegistered(TestIdentifier testIdentifier) { } /** * Called when the execution of a leaf or subtree of the {@link TestPlan} * has been skipped. * *

The {@link TestIdentifier} may represent a test or a container. In * the case of a container, no listener methods will be called for any of * its descendants. * *

A skipped test or subtree of tests will never be reported as * {@linkplain #executionStarted started} or * {@linkplain #executionFinished finished}. * * @param testIdentifier the identifier of the skipped test or container * @param reason a human-readable message describing why the execution * has been skipped */ default void executionSkipped(TestIdentifier testIdentifier, String reason) { } /** * Called when the execution of a leaf or subtree of the {@link TestPlan} * is about to be started. * *

The {@link TestIdentifier} may represent a test or a container. * *

This method will only be called if the test or container has not * been {@linkplain #executionSkipped skipped}. * *

This method will be called for a container {@code TestIdentifier} * before {@linkplain #executionStarted starting} or * {@linkplain #executionSkipped skipping} any of its children. * * @param testIdentifier the identifier of the started test or container */ default void executionStarted(TestIdentifier testIdentifier) { } /** * Called when the execution of a leaf or subtree of the {@link TestPlan} * has finished, regardless of the outcome. * *

The {@link TestIdentifier} may represent a test or a container. * *

This method will only be called if the test or container has not * been {@linkplain #executionSkipped skipped}. * *

This method will be called for a container {@code TestIdentifier} * after all of its children have been * {@linkplain #executionSkipped skipped} or have * {@linkplain #executionFinished finished}. * *

The {@link TestExecutionResult} describes the result of the execution * for the supplied {@code TestIdentifier}. The result does not include or * aggregate the results of its children. For example, a container with a * failing test will be reported as {@link Status#SUCCESSFUL SUCCESSFUL} even * if one or more of its children are reported as {@link Status#FAILED FAILED}. * * @param testIdentifier the identifier of the finished test or container * @param testExecutionResult the (unaggregated) result of the execution for * the supplied {@code TestIdentifier} * * @see TestExecutionResult */ default void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { } /** * Called when additional test reporting data has been published for * the supplied {@link TestIdentifier}. * *

Can be called at any time during the execution of a test plan. * * @param testIdentifier describes the test or container to which the entry pertains * @param entry the published {@code ReportEntry} */ default void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { } } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java000066400000000000000000000262611455764576500335760ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.unmodifiableSet; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamField; import java.io.Serializable; import java.util.LinkedHashSet; import java.util.Objects; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestDescriptor.Type; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; /** * Immutable data transfer object that represents a test or container which is * usually part of a {@link TestPlan}. * * @since 1.0 * @see TestPlan */ @API(status = STABLE, since = "1.0") public final class TestIdentifier implements Serializable { private static final long serialVersionUID = 1L; private static final ObjectStreamField[] serialPersistentFields = ObjectStreamClass.lookup( SerializedForm.class).getFields(); // These are effectively final but not technically due to late initialization when deserializing private /* final */ UniqueId uniqueId; private /* final */ UniqueId parentId; private /* final */ String displayName; private /* final */ String legacyReportingName; private /* final */ TestSource source; private /* final */ Set tags; private /* final */ Type type; /** * Factory for creating a new {@link TestIdentifier} from a {@link TestDescriptor}. */ @API(status = INTERNAL, since = "1.0") public static TestIdentifier from(TestDescriptor testDescriptor) { Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); UniqueId uniqueId = testDescriptor.getUniqueId(); String displayName = testDescriptor.getDisplayName(); TestSource source = testDescriptor.getSource().orElse(null); Set tags = testDescriptor.getTags(); Type type = testDescriptor.getType(); UniqueId parentId = testDescriptor.getParent().map(TestDescriptor::getUniqueId).orElse(null); String legacyReportingName = testDescriptor.getLegacyReportingName(); return new TestIdentifier(uniqueId, displayName, source, tags, type, parentId, legacyReportingName); } private TestIdentifier(UniqueId uniqueId, String displayName, TestSource source, Set tags, Type type, UniqueId parentId, String legacyReportingName) { Preconditions.notNull(type, "TestDescriptor.Type must not be null"); this.uniqueId = uniqueId; this.parentId = parentId; this.displayName = displayName; this.source = source; this.tags = copyOf(tags); this.type = type; this.legacyReportingName = legacyReportingName; } private Set copyOf(Set tags) { switch (tags.size()) { case 0: return emptySet(); case 1: return singleton(getOnlyElement(tags)); default: return new LinkedHashSet<>(tags); } } /** * Get the unique ID of the represented test or container as a * {@code String}. * *

Uniqueness must be guaranteed across an entire * {@linkplain TestPlan test plan}, regardless of how many engines are used * behind the scenes. * * @return the unique ID for this identifier; never {@code null} */ public String getUniqueId() { return this.uniqueId.toString(); } /** * Get the unique ID of the represented test or container as a * {@code UniqueId}. * *

Uniqueness must be guaranteed across an entire * {@linkplain TestPlan test plan}, regardless of how many engines are used * behind the scenes. * * @return the unique ID for this identifier; never {@code null} * @since 5.8 */ @API(status = STABLE, since = "5.8") public UniqueId getUniqueIdObject() { return this.uniqueId; } /** * Get the unique ID of this identifier's parent as a {@code String}, if * available. * *

An identifier without a parent is called a root. * * @return a container for the unique ID for this identifier's parent; * never {@code null} though potentially empty */ public Optional getParentId() { return getParentIdObject().map(UniqueId::toString); } /** * Get the unique ID of this identifier's parent as a {@code UniqueId}, if * available. * *

An identifier without a parent is called a root. * * @return a container for the unique ID for this identifier's parent; * never {@code null} though potentially empty * @since 5.8 */ @API(status = STABLE, since = "5.8") public Optional getParentIdObject() { return Optional.ofNullable(this.parentId); } /** * Get the display name of the represented test or container. * *

A display name is a human-readable name for a test or * container that is typically used for test reporting in IDEs and build * tools. Display names may contain spaces, special characters, and emoji, * and the format may be customized by {@link org.junit.platform.engine.TestEngine * TestEngines} or potentially by end users as well. Consequently, display * names should never be parsed; rather, they should be used for display * purposes only. * * @return the display name for this identifier; never {@code null} or blank * @see #getSource() * @see org.junit.platform.engine.TestDescriptor#getDisplayName() */ public String getDisplayName() { return this.displayName; } /** * Get the name of this identifier in a format that is suitable for legacy * reporting infrastructure — for example, for reporting systems built * on the Ant-based XML reporting format for JUnit 4. * *

The default implementation delegates to {@link #getDisplayName()}. * * @return the legacy reporting name; never {@code null} or blank * @see org.junit.platform.engine.TestDescriptor#getLegacyReportingName() * @see org.junit.platform.reporting.legacy.LegacyReportingUtils */ @SuppressWarnings("JavadocReference") public String getLegacyReportingName() { return this.legacyReportingName; } /** * Get the underlying descriptor type. * * @return the underlying descriptor type; never {@code null} */ public Type getType() { return type; } /** * Determine if this identifier represents a test. * * @return {@code true} if the underlying descriptor type represents a test, * {@code false} otherwise * @see Type#isTest() */ public boolean isTest() { return getType().isTest(); } /** * Determine if this identifier represents a container. * * @return {@code true} if the underlying descriptor type represents a container, * {@code false} otherwise * @see Type#isContainer() */ public boolean isContainer() { return getType().isContainer(); } /** * Get the {@linkplain TestSource source} of the represented test * or container, if available. * * @see TestSource */ public Optional getSource() { return Optional.ofNullable(this.source); } /** * Get the set of {@linkplain TestTag tags} associated with the represented * test or container. * * @see TestTag */ public Set getTags() { return unmodifiableSet(this.tags); } @Override public boolean equals(Object obj) { if (obj instanceof TestIdentifier) { TestIdentifier that = (TestIdentifier) obj; return Objects.equals(this.uniqueId, that.uniqueId); } return false; } @Override public int hashCode() { return this.uniqueId.hashCode(); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("uniqueId", this.uniqueId) .append("parentId", this.parentId) .append("displayName", this.displayName) .append("legacyReportingName", this.legacyReportingName) .append("source", this.source) .append("tags", this.tags) .append("type", this.type) .toString(); // @formatter:on } private void writeObject(ObjectOutputStream s) throws IOException { SerializedForm serializedForm = new SerializedForm(this); serializedForm.serialize(s); } private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { SerializedForm serializedForm = SerializedForm.deserialize(s); uniqueId = UniqueId.parse(serializedForm.uniqueId); displayName = serializedForm.displayName; source = serializedForm.source; tags = serializedForm.tags; type = serializedForm.type; parentId = UniqueId.parse(serializedForm.parentId); legacyReportingName = serializedForm.legacyReportingName; } /** * Represents the serialized output of {@code TestIdentifier}. The fields on this * class match the fields that {@code TestIdentifier} had prior to 5.8. */ private static class SerializedForm implements Serializable { private static final long serialVersionUID = 1L; private final String uniqueId; private final String parentId; private final String displayName; private final String legacyReportingName; private final TestSource source; @SuppressWarnings({ "serial", "RedundantSuppression" }) // always used with serializable implementation (see TestIdentifier#copyOf()) private final Set tags; private final Type type; SerializedForm(TestIdentifier testIdentifier) { this.uniqueId = testIdentifier.uniqueId.toString(); this.parentId = testIdentifier.parentId.toString(); this.displayName = testIdentifier.displayName; this.legacyReportingName = testIdentifier.legacyReportingName; this.source = testIdentifier.source; this.tags = testIdentifier.tags; this.type = testIdentifier.type; } @SuppressWarnings("unchecked") private SerializedForm(ObjectInputStream.GetField fields) throws IOException { this.uniqueId = (String) fields.get("uniqueId", null); this.parentId = (String) fields.get("parentId", null); this.displayName = (String) fields.get("displayName", null); this.legacyReportingName = (String) fields.get("legacyReportingName", null); this.source = (TestSource) fields.get("source", null); this.tags = (Set) fields.get("tags", null); this.type = (Type) fields.get("type", null); } void serialize(ObjectOutputStream s) throws IOException { ObjectOutputStream.PutField fields = s.putFields(); fields.put("uniqueId", uniqueId); fields.put("parentId", parentId); fields.put("displayName", displayName); fields.put("legacyReportingName", legacyReportingName); fields.put("source", source); fields.put("tags", tags); fields.put("type", type); s.writeFields(); } static SerializedForm deserialize(ObjectInputStream s) throws ClassNotFoundException, IOException { ObjectInputStream.GetField fields = s.readFields(); return new SerializedForm(fields); } } } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java000066400000000000000000000305061455764576500324030ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static java.util.Collections.emptySet; import static java.util.Collections.synchronizedSet; import static java.util.Collections.unmodifiableSet; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; /** * {@code TestPlan} describes the tree of tests and containers as discovered * by a {@link Launcher}. * *

Tests and containers are represented by {@link TestIdentifier} instances. * The complete set of identifiers comprises a tree-like structure. However, * each identifier only stores the unique ID of its parent. This class provides * a number of helpful methods to retrieve the * {@linkplain #getParent(TestIdentifier) parent}, * {@linkplain #getChildren(TestIdentifier) children}, and * {@linkplain #getDescendants(TestIdentifier) descendants} of an identifier. * *

While the contained instances of {@link TestIdentifier} are immutable, * instances of this class contain mutable state. For example, when a dynamic * test is registered at runtime, it is added to the original test plan and * reported to {@link TestExecutionListener} implementations. * *

This class is not intended to be extended by clients. * * @since 1.0 * @see Launcher * @see TestExecutionListener */ @API(status = STABLE, since = "1.0") public class TestPlan { private final Set roots = synchronizedSet(new LinkedHashSet<>(4)); private final Map> children = new ConcurrentHashMap<>(32); private final Map allIdentifiers = new ConcurrentHashMap<>(32); private final boolean containsTests; private final ConfigurationParameters configurationParameters; /** * Construct a new {@code TestPlan} from the supplied collection of * {@link TestDescriptor TestDescriptors}. * *

Each supplied {@code TestDescriptor} is expected to be a descriptor * for a {@link org.junit.platform.engine.TestEngine TestEngine}. * * @param engineDescriptors the engine test descriptors from which the test * plan should be created; never {@code null} * @param configurationParameters the {@code ConfigurationParameters} for * this test plan; never {@code null} * @return a new test plan */ @API(status = INTERNAL, since = "1.0") public static TestPlan from(Collection engineDescriptors, ConfigurationParameters configurationParameters) { Preconditions.notNull(engineDescriptors, "Cannot create TestPlan from a null collection of TestDescriptors"); Preconditions.notNull(configurationParameters, "Cannot create TestPlan from null ConfigurationParameters"); TestPlan testPlan = new TestPlan(engineDescriptors.stream().anyMatch(TestDescriptor::containsTests), configurationParameters); TestDescriptor.Visitor visitor = descriptor -> testPlan.addInternal(TestIdentifier.from(descriptor)); engineDescriptors.forEach(engineDescriptor -> engineDescriptor.accept(visitor)); return testPlan; } @API(status = INTERNAL, since = "1.4") protected TestPlan(boolean containsTests, ConfigurationParameters configurationParameters) { this.containsTests = containsTests; this.configurationParameters = configurationParameters; } /** * Add the supplied {@link TestIdentifier} to this test plan. * * @param testIdentifier the identifier to add; never {@code null} * @deprecated Calling this method is no longer supported and will throw an * exception. * @throws JUnitException always */ @Deprecated @API(status = DEPRECATED, since = "1.4") public void add(@SuppressWarnings("unused") TestIdentifier testIdentifier) { throw new JUnitException("Unsupported attempt to modify the TestPlan was detected. " + "Please contact your IDE/tool vendor and request a fix or downgrade to JUnit 5.7.x (see https://github.com/junit-team/junit5/issues/1732 for details)."); } @API(status = INTERNAL, since = "1.8") public void addInternal(TestIdentifier testIdentifier) { Preconditions.notNull(testIdentifier, "testIdentifier must not be null"); allIdentifiers.put(testIdentifier.getUniqueIdObject(), testIdentifier); // Root identifiers. Typically, a test engine. if (!testIdentifier.getParentIdObject().isPresent()) { roots.add(testIdentifier); return; } // Identifiers without a parent in this test plan. Could be a test // engine that is used in a suite. UniqueId parentId = testIdentifier.getParentIdObject().get(); if (!allIdentifiers.containsKey(parentId)) { roots.add(testIdentifier); return; } Set directChildren = children.computeIfAbsent(parentId, key -> synchronizedSet(new LinkedHashSet<>(16))); directChildren.add(testIdentifier); } /** * Get the root {@link TestIdentifier TestIdentifiers} for this test plan. * * @return an unmodifiable set of the root identifiers */ public Set getRoots() { return unmodifiableSet(roots); } /** * Get the parent of the supplied {@link TestIdentifier}. * * @param child the identifier to look up the parent for; never {@code null} * @return an {@code Optional} containing the parent, if present */ public Optional getParent(TestIdentifier child) { Preconditions.notNull(child, "child must not be null"); return child.getParentIdObject().map(this::getTestIdentifier); } /** * Get the children of the supplied {@link TestIdentifier}. * * @param parent the identifier to look up the children for; never {@code null} * @return an unmodifiable set of the parent's children, potentially empty * @see #getChildren(UniqueId) */ public Set getChildren(TestIdentifier parent) { Preconditions.notNull(parent, "parent must not be null"); return getChildren(parent.getUniqueIdObject()); } /** * Get the children of the supplied unique ID. * * @param parentId the unique ID to look up the children for; never * {@code null} or blank * @return an unmodifiable set of the parent's children, potentially empty * @see #getChildren(TestIdentifier) * @deprecated Use {@link #getChildren(UniqueId)} */ @API(status = DEPRECATED, since = "1.10") @Deprecated public Set getChildren(String parentId) { Preconditions.notBlank(parentId, "parent ID must not be null or blank"); return getChildren(UniqueId.parse(parentId)); } /** * Get the children of the supplied unique ID. * * @param parentId the unique ID to look up the children for; never * {@code null} * @return an unmodifiable set of the parent's children, potentially empty * @see #getChildren(TestIdentifier) */ @API(status = MAINTAINED, since = "1.10") public Set getChildren(UniqueId parentId) { return children.containsKey(parentId) ? unmodifiableSet(children.get(parentId)) : emptySet(); } /** * Get the {@link TestIdentifier} with the supplied unique ID. * * @param uniqueId the unique ID to look up the identifier for; never * {@code null} or blank * @return the identifier with the supplied unique ID; never {@code null} * @throws PreconditionViolationException if no {@code TestIdentifier} * with the supplied unique ID is present in this test plan * @deprecated Use {@link #getTestIdentifier(UniqueId)} */ @API(status = DEPRECATED, since = "1.10") @Deprecated public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { Preconditions.notBlank(uniqueId, "unique ID must not be null or blank"); return getTestIdentifier(UniqueId.parse(uniqueId)); } /** * Get the {@link TestIdentifier} with the supplied unique ID. * * @param uniqueId the unique ID to look up the identifier for; never * {@code null} * @return the identifier with the supplied unique ID; never {@code null} * @throws PreconditionViolationException if no {@code TestIdentifier} * with the supplied unique ID is present in this test plan */ @API(status = MAINTAINED, since = "1.10") public TestIdentifier getTestIdentifier(UniqueId uniqueId) { Preconditions.notNull(uniqueId, () -> "uniqueId must not be null"); return Preconditions.notNull(allIdentifiers.get(uniqueId), () -> "No TestIdentifier with unique ID [" + uniqueId + "] has been added to this TestPlan."); } /** * Count all {@link TestIdentifier TestIdentifiers} that satisfy the * given {@linkplain Predicate predicate}. * * @param predicate a predicate which returns {@code true} for identifiers * to be counted; never {@code null} * @return the number of identifiers that satisfy the supplied predicate */ public long countTestIdentifiers(Predicate predicate) { Preconditions.notNull(predicate, "Predicate must not be null"); return allIdentifiers.values().stream().filter(predicate).count(); } /** * Get all descendants of the supplied {@link TestIdentifier} (i.e., * all of its children and their children, recursively). * * @param parent the identifier to look up the descendants for; never {@code null} * @return an unmodifiable set of the parent's descendants, potentially empty */ public Set getDescendants(TestIdentifier parent) { Preconditions.notNull(parent, "parent must not be null"); Set result = new LinkedHashSet<>(16); Set children = getChildren(parent); result.addAll(children); for (TestIdentifier child : children) { result.addAll(getDescendants(child)); } return unmodifiableSet(result); } /** * Return whether this test plan contains any tests. * *

A test plan contains tests, if at least one of the contained engine * descriptors {@linkplain TestDescriptor#containsTests(TestDescriptor) * contains tests}. * * @return {@code true} if this test plan contains tests * @see TestDescriptor#containsTests(TestDescriptor) */ public boolean containsTests() { return containsTests; } /** * Get the {@link ConfigurationParameters} for this test plan. * * @return the configuration parameters; never {@code null} * @since 1.8 */ @API(status = MAINTAINED, since = "1.8") public ConfigurationParameters getConfigurationParameters() { return this.configurationParameters; } /** * Accept the supplied {@link Visitor} for a depth-first traversal of the * test plan. * * @param visitor the visitor to accept; never {@code null} * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public void accept(Visitor visitor) { getRoots().forEach(it -> accept(visitor, it)); } private void accept(Visitor visitor, TestIdentifier testIdentifier) { if (testIdentifier.isContainer()) { visitor.preVisitContainer(testIdentifier); } visitor.visit(testIdentifier); getChildren(testIdentifier).forEach(it -> accept(visitor, it)); if (testIdentifier.isContainer()) { visitor.postVisitContainer(testIdentifier); } } /** * Visitor for {@link TestIdentifier TestIdentifiers} in a {@link TestPlan}. * * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") public interface Visitor { /** * Called before visiting a container. * * @see TestIdentifier#isContainer() */ default void preVisitContainer(TestIdentifier testIdentifier) { } /** * Called for all test identifiers regardless of their type. */ default void visit(TestIdentifier testIdentifier) { } /** * Called after visiting a container. * * @see TestIdentifier#isContainer() */ default void postVisitContainer(TestIdentifier testIdentifier) { } } } junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/000077500000000000000000000000001455764576500307325ustar00rootroot00000000000000CompositeEngineExecutionListener.java000066400000000000000000000064011455764576500402010ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; class CompositeEngineExecutionListener implements EngineExecutionListener { private static final Logger logger = LoggerFactory.getLogger(CompositeEngineExecutionListener.class); private final List engineExecutionListeners; CompositeEngineExecutionListener(List engineExecutionListeners) { this.engineExecutionListeners = new ArrayList<>(engineExecutionListeners); } @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { notifyEach(engineExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.dynamicTestRegistered(testDescriptor), () -> "dynamicTestRegistered(" + testDescriptor + ")"); } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { notifyEach(engineExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.executionSkipped(testDescriptor, reason), () -> "executionSkipped(" + testDescriptor + ", " + reason + ")"); } @Override public void executionStarted(TestDescriptor testDescriptor) { notifyEach(engineExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.executionStarted(testDescriptor), () -> "executionStarted(" + testDescriptor + ")"); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { notifyEach(engineExecutionListeners, IterationOrder.REVERSED, listener -> listener.executionFinished(testDescriptor, testExecutionResult), () -> "executionFinished(" + testDescriptor + ", " + testExecutionResult + ")"); } @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { notifyEach(engineExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.reportingEntryPublished(testDescriptor, entry), () -> "reportingEntryPublished(" + testDescriptor + ", " + entry + ")"); } private static void notifyEach(List listeners, IterationOrder iterationOrder, Consumer consumer, Supplier description) { iterationOrder.forEach(listeners, listener -> { try { consumer.accept(listener); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.warn(throwable, () -> String.format("EngineExecutionListener [%s] threw exception for method: %s", listener.getClass().getName(), description.get())); } }); } } CompositeTestExecutionListener.java000066400000000000000000000114131455764576500377120ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.toList; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; class CompositeTestExecutionListener implements TestExecutionListener { private static final Logger logger = LoggerFactory.getLogger(CompositeTestExecutionListener.class); private final List testExecutionListeners; private final List eagerTestExecutionListeners; CompositeTestExecutionListener(List testExecutionListeners) { this.testExecutionListeners = new ArrayList<>(testExecutionListeners); this.eagerTestExecutionListeners = this.testExecutionListeners.stream() // .filter(EagerTestExecutionListener.class::isInstance) // .map(EagerTestExecutionListener.class::cast) // .collect(toList()); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { notifyEach(testExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.dynamicTestRegistered(testIdentifier), () -> "dynamicTestRegistered(" + testIdentifier + ")"); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { notifyEach(testExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.executionSkipped(testIdentifier, reason), () -> "executionSkipped(" + testIdentifier + ", " + reason + ")"); } @Override public void executionStarted(TestIdentifier testIdentifier) { notifyEach(eagerTestExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.executionJustStarted(testIdentifier), () -> "executionJustStarted(" + testIdentifier + ")"); notifyEach(testExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.executionStarted(testIdentifier), () -> "executionStarted(" + testIdentifier + ")"); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { notifyEach(eagerTestExecutionListeners, IterationOrder.REVERSED, listener -> listener.executionJustFinished(testIdentifier, testExecutionResult), () -> "executionJustFinished(" + testIdentifier + ", " + testExecutionResult + ")"); notifyEach(testExecutionListeners, IterationOrder.REVERSED, listener -> listener.executionFinished(testIdentifier, testExecutionResult), () -> "executionFinished(" + testIdentifier + ", " + testExecutionResult + ")"); } @Override public void testPlanExecutionStarted(TestPlan testPlan) { notifyEach(testExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.testPlanExecutionStarted(testPlan), () -> "testPlanExecutionStarted(" + testPlan + ")"); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { notifyEach(testExecutionListeners, IterationOrder.REVERSED, listener -> listener.testPlanExecutionFinished(testPlan), () -> "testPlanExecutionFinished(" + testPlan + ")"); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { notifyEach(testExecutionListeners, IterationOrder.ORIGINAL, listener -> listener.reportingEntryPublished(testIdentifier, entry), () -> "reportingEntryPublished(" + testIdentifier + ", " + entry + ")"); } private static void notifyEach(List listeners, IterationOrder iterationOrder, Consumer consumer, Supplier description) { iterationOrder.forEach(listeners, listener -> { try { consumer.accept(listener); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.warn(throwable, () -> String.format("TestExecutionListener [%s] threw exception for method: %s", listener.getClass().getName(), description.get())); } }); } interface EagerTestExecutionListener extends TestExecutionListener { default void executionJustStarted(TestIdentifier testIdentifier) { } default void executionJustFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { } } } DefaultDiscoveryRequest.java000066400000000000000000000070701455764576500363470ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableList; import static java.util.stream.Collectors.toList; import java.util.List; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.launcher.EngineFilter; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; /** * {@code DefaultDiscoveryRequest} is the default implementation of the * {@link EngineDiscoveryRequest} and {@link LauncherDiscoveryRequest} APIs. * * @since 1.0 */ final class DefaultDiscoveryRequest implements LauncherDiscoveryRequest { // Selectors provided to the engines to be used for discovering tests private final List selectors; // Filters based on engines private final List engineFilters; // Discovery filters are handed through to all engines to be applied during discovery. private final List> discoveryFilters; // Descriptor filters are applied by the launcher itself after engines have performed discovery. private final List postDiscoveryFilters; // Configuration parameters can be used to provide custom configuration to engines, e.g. for extensions private final LauncherConfigurationParameters configurationParameters; // Listener for test discovery that may abort on errors. private final LauncherDiscoveryListener discoveryListener; DefaultDiscoveryRequest(List selectors, List engineFilters, List> discoveryFilters, List postDiscoveryFilters, LauncherConfigurationParameters configurationParameters, LauncherDiscoveryListener discoveryListener) { this.selectors = selectors; this.engineFilters = engineFilters; this.discoveryFilters = discoveryFilters; this.postDiscoveryFilters = postDiscoveryFilters; this.configurationParameters = configurationParameters; this.discoveryListener = discoveryListener; } @Override public List getSelectorsByType(Class selectorType) { Preconditions.notNull(selectorType, "selectorType must not be null"); return this.selectors.stream().filter(selectorType::isInstance).map(selectorType::cast).collect(toList()); } @Override public List getEngineFilters() { return unmodifiableList(this.engineFilters); } @Override public > List getFiltersByType(Class filterType) { Preconditions.notNull(filterType, "filterType must not be null"); return this.discoveryFilters.stream().filter(filterType::isInstance).map(filterType::cast).collect(toList()); } @Override public List getPostDiscoveryFilters() { return unmodifiableList(this.postDiscoveryFilters); } @Override public ConfigurationParameters getConfigurationParameters() { return this.configurationParameters; } @Override public LauncherDiscoveryListener getDiscoveryListener() { return discoveryListener; } } DefaultLauncher.java000066400000000000000000000107101455764576500345630ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableCollection; import static org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.Phase.DISCOVERY; import static org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.Phase.EXECUTION; import java.util.Collection; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * Default implementation of the {@link Launcher} API. * *

External clients can obtain an instance by invoking * {@link LauncherFactory#create()}. * * @since 1.0 * @see Launcher * @see LauncherFactory */ class DefaultLauncher implements Launcher { private final LauncherListenerRegistry listenerRegistry = new LauncherListenerRegistry(); private final EngineExecutionOrchestrator executionOrchestrator = new EngineExecutionOrchestrator( listenerRegistry.testExecutionListeners);; private final EngineDiscoveryOrchestrator discoveryOrchestrator; /** * Construct a new {@code DefaultLauncher} with the supplied test engines. * * @param testEngines the test engines to delegate to; never {@code null} or * empty * @param postDiscoveryFilters the additional post discovery filters for * discovery requests; never {@code null} */ DefaultLauncher(Iterable testEngines, Collection postDiscoveryFilters) { Preconditions.condition(testEngines != null && testEngines.iterator().hasNext(), () -> "Cannot create Launcher without at least one TestEngine; " + "consider adding an engine implementation JAR to the classpath"); Preconditions.notNull(postDiscoveryFilters, "PostDiscoveryFilter array must not be null"); Preconditions.containsNoNullElements(postDiscoveryFilters, "PostDiscoveryFilter array must not contain null elements"); this.discoveryOrchestrator = new EngineDiscoveryOrchestrator(testEngines, unmodifiableCollection(postDiscoveryFilters), listenerRegistry.launcherDiscoveryListeners); } @Override public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { this.listenerRegistry.launcherDiscoveryListeners.addAll(listeners); } @Override public void registerTestExecutionListeners(TestExecutionListener... listeners) { this.listenerRegistry.testExecutionListeners.addAll(listeners); } @Override public TestPlan discover(LauncherDiscoveryRequest discoveryRequest) { Preconditions.notNull(discoveryRequest, "LauncherDiscoveryRequest must not be null"); return InternalTestPlan.from(discover(discoveryRequest, DISCOVERY)); } @Override public void execute(LauncherDiscoveryRequest discoveryRequest, TestExecutionListener... listeners) { Preconditions.notNull(discoveryRequest, "LauncherDiscoveryRequest must not be null"); Preconditions.notNull(listeners, "TestExecutionListener array must not be null"); Preconditions.containsNoNullElements(listeners, "individual listeners must not be null"); execute(InternalTestPlan.from(discover(discoveryRequest, EXECUTION)), listeners); } @Override public void execute(TestPlan testPlan, TestExecutionListener... listeners) { Preconditions.notNull(testPlan, "TestPlan must not be null"); Preconditions.condition(testPlan instanceof InternalTestPlan, "TestPlan was not returned by this Launcher"); Preconditions.notNull(listeners, "TestExecutionListener array must not be null"); Preconditions.containsNoNullElements(listeners, "individual listeners must not be null"); execute((InternalTestPlan) testPlan, listeners); } private LauncherDiscoveryResult discover(LauncherDiscoveryRequest discoveryRequest, EngineDiscoveryOrchestrator.Phase phase) { return discoveryOrchestrator.discover(discoveryRequest, phase); } private void execute(InternalTestPlan internalTestPlan, TestExecutionListener[] listeners) { executionOrchestrator.execute(internalTestPlan, listeners); } } DefaultLauncherConfig.java000066400000000000000000000110021455764576500357040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableCollection; import java.util.Collection; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.TestExecutionListener; /** * Default implementation of the {@link LauncherConfig} API. * * @since 1.3 */ class DefaultLauncherConfig implements LauncherConfig { private final boolean testEngineAutoRegistrationEnabled; private final boolean launcherSessionListenerAutoRegistrationEnabled; private final boolean launcherDiscoveryListenerAutoRegistrationEnabled; private final boolean testExecutionListenerAutoRegistrationEnabled; private final boolean postDiscoveryFilterAutoRegistrationEnabled; private final Collection additionalTestEngines; private final Collection additionalLauncherSessionListeners; private final Collection additionalLauncherDiscoveryListeners; private final Collection additionalTestExecutionListeners; private final Collection additionalPostDiscoveryFilters; DefaultLauncherConfig(boolean testEngineAutoRegistrationEnabled, boolean launcherSessionListenerAutoRegistrationEnabled, boolean launcherDiscoveryListenerAutoRegistrationEnabled, boolean testExecutionListenerAutoRegistrationEnabled, boolean postDiscoveryFilterAutoRegistrationEnabled, Collection additionalTestEngines, Collection additionalLauncherSessionListeners, Collection additionalLauncherDiscoveryListeners, Collection additionalTestExecutionListeners, Collection additionalPostDiscoveryFilters) { this.launcherSessionListenerAutoRegistrationEnabled = launcherSessionListenerAutoRegistrationEnabled; this.launcherDiscoveryListenerAutoRegistrationEnabled = launcherDiscoveryListenerAutoRegistrationEnabled; this.testExecutionListenerAutoRegistrationEnabled = testExecutionListenerAutoRegistrationEnabled; this.testEngineAutoRegistrationEnabled = testEngineAutoRegistrationEnabled; this.postDiscoveryFilterAutoRegistrationEnabled = postDiscoveryFilterAutoRegistrationEnabled; this.additionalTestEngines = unmodifiableCollection(additionalTestEngines); this.additionalLauncherSessionListeners = unmodifiableCollection(additionalLauncherSessionListeners); this.additionalLauncherDiscoveryListeners = unmodifiableCollection(additionalLauncherDiscoveryListeners); this.additionalTestExecutionListeners = unmodifiableCollection(additionalTestExecutionListeners); this.additionalPostDiscoveryFilters = unmodifiableCollection(additionalPostDiscoveryFilters); } @Override public boolean isTestEngineAutoRegistrationEnabled() { return this.testEngineAutoRegistrationEnabled; } @Override public boolean isLauncherSessionListenerAutoRegistrationEnabled() { return launcherSessionListenerAutoRegistrationEnabled; } @Override public boolean isLauncherDiscoveryListenerAutoRegistrationEnabled() { return launcherDiscoveryListenerAutoRegistrationEnabled; } @Override public boolean isTestExecutionListenerAutoRegistrationEnabled() { return this.testExecutionListenerAutoRegistrationEnabled; } @Override public boolean isPostDiscoveryFilterAutoRegistrationEnabled() { return this.postDiscoveryFilterAutoRegistrationEnabled; } @Override public Collection getAdditionalTestEngines() { return this.additionalTestEngines; } @Override public Collection getAdditionalLauncherSessionListeners() { return additionalLauncherSessionListeners; } @Override public Collection getAdditionalLauncherDiscoveryListeners() { return additionalLauncherDiscoveryListeners; } @Override public Collection getAdditionalTestExecutionListeners() { return this.additionalTestExecutionListeners; } @Override public Collection getAdditionalPostDiscoveryFilters() { return this.additionalPostDiscoveryFilters; } } DefaultLauncherSession.java000066400000000000000000000077151455764576500361420ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.List; import java.util.function.Supplier; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * @since 1.8 */ class DefaultLauncherSession implements LauncherSession { private static final LauncherInterceptor NOOP_INTERCEPTOR = new LauncherInterceptor() { @Override public T intercept(Invocation invocation) { return invocation.proceed(); } @Override public void close() { // do nothing } }; private final LauncherInterceptor interceptor; private final LauncherSessionListener listener; private final DelegatingLauncher launcher; DefaultLauncherSession(List interceptors, Supplier listenerSupplier, Supplier launcherSupplier) { interceptor = composite(interceptors); Launcher launcher; if (interceptor == NOOP_INTERCEPTOR) { this.listener = listenerSupplier.get(); launcher = launcherSupplier.get(); } else { this.listener = interceptor.intercept(listenerSupplier::get); launcher = new InterceptingLauncher(interceptor.intercept(launcherSupplier::get), interceptor); } this.launcher = new DelegatingLauncher(launcher); listener.launcherSessionOpened(this); } @Override public Launcher getLauncher() { return launcher; } LauncherSessionListener getListener() { return listener; } @Override public void close() { if (launcher.delegate != ClosedLauncher.INSTANCE) { launcher.delegate = ClosedLauncher.INSTANCE; listener.launcherSessionClosed(this); interceptor.close(); } } private static class ClosedLauncher implements Launcher { static final ClosedLauncher INSTANCE = new ClosedLauncher(); private ClosedLauncher() { } @Override public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } @Override public void registerTestExecutionListeners(TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } @Override public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { throw new PreconditionViolationException("Launcher session has already been closed"); } @Override public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } @Override public void execute(TestPlan testPlan, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } } private static LauncherInterceptor composite(List interceptors) { if (interceptors.isEmpty()) { return NOOP_INTERCEPTOR; } return interceptors.stream() // .skip(1) // .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { @Override public void close() { try { a.close(); } finally { b.close(); } } @Override public T intercept(Invocation invocation) { return a.intercept(() -> b.intercept(invocation)); } }); } } DelegatingEngineExecutionListener.java000066400000000000000000000030571455764576500403060ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; /** * @since 1.6 */ class DelegatingEngineExecutionListener implements EngineExecutionListener { private final EngineExecutionListener delegate; DelegatingEngineExecutionListener(EngineExecutionListener delegate) { this.delegate = delegate; } @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { delegate.dynamicTestRegistered(testDescriptor); } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { delegate.executionSkipped(testDescriptor, reason); } @Override public void executionStarted(TestDescriptor testDescriptor) { delegate.executionStarted(testDescriptor); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { delegate.executionFinished(testDescriptor, testExecutionResult); } @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { delegate.reportingEntryPublished(testDescriptor, entry); } } DelegatingLauncher.java000066400000000000000000000030611455764576500352430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * @since 1.10 */ class DelegatingLauncher implements Launcher { protected Launcher delegate; DelegatingLauncher(Launcher delegate) { this.delegate = delegate; } @Override public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { delegate.registerLauncherDiscoveryListeners(listeners); } @Override public void registerTestExecutionListeners(TestExecutionListener... listeners) { delegate.registerTestExecutionListeners(listeners); } @Override public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { return delegate.discover(launcherDiscoveryRequest); } @Override public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { delegate.execute(launcherDiscoveryRequest, listeners); } @Override public void execute(TestPlan testPlan, TestExecutionListener... listeners) { delegate.execute(testPlan, listeners); } } EngineDiscoveryErrorDescriptor.java000066400000000000000000000025071455764576500376700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; /** * Represents an error thrown by a {@link org.junit.platform.engine.TestEngine} * during discovery. * *

The contained {@link Throwable} will be reported as the cause of a test * failure by the {@link DefaultLauncher} when execution is started for this * engine. * * @since 1.6 */ class EngineDiscoveryErrorDescriptor extends AbstractTestDescriptor { private final Throwable cause; EngineDiscoveryErrorDescriptor(UniqueId uniqueId, TestEngine testEngine, Throwable cause) { super(uniqueId, testEngine.getId(), ClassSource.from(testEngine.getClass())); this.cause = cause; } Throwable getCause() { return cause; } @Override public Type getType() { return Type.TEST; } @Override public void prune() { // prevent pruning } } EngineDiscoveryOrchestrator.java000066400000000000000000000241641455764576500372220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.engine.Filter.composeFilters; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.Filter; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; /** * Orchestrates test discovery using the configured test engines. * * @since 1.7 */ @API(status = INTERNAL, since = "1.7", consumers = { "org.junit.platform.testkit", "org.junit.platform.suite.engine" }) public class EngineDiscoveryOrchestrator { private static final Logger logger = LoggerFactory.getLogger(EngineDiscoveryOrchestrator.class); private final EngineDiscoveryResultValidator discoveryResultValidator = new EngineDiscoveryResultValidator(); private final Iterable testEngines; private final Collection postDiscoveryFilters; private final ListenerRegistry launcherDiscoveryListenerRegistry; public EngineDiscoveryOrchestrator(Iterable testEngines, Collection postDiscoveryFilters) { this(testEngines, postDiscoveryFilters, ListenerRegistry.forLauncherDiscoveryListeners()); } EngineDiscoveryOrchestrator(Iterable testEngines, Collection postDiscoveryFilters, ListenerRegistry launcherDiscoveryListenerRegistry) { this.testEngines = EngineIdValidator.validate(testEngines); this.postDiscoveryFilters = postDiscoveryFilters; this.launcherDiscoveryListenerRegistry = launcherDiscoveryListenerRegistry; } /** * Discovers tests for the supplied request in the supplied phase using the * configured test engines. * *

Applies {@linkplain org.junit.platform.launcher.EngineFilter engine * filters} and {@linkplain PostDiscoveryFilter post-discovery filters} and * {@linkplain TestDescriptor#prune() prunes} the resulting test tree. */ public LauncherDiscoveryResult discover(LauncherDiscoveryRequest request, Phase phase) { Map result = discover(request, phase, UniqueId::forEngine); return new LauncherDiscoveryResult(result, request.getConfigurationParameters()); } /** * Discovers tests for the supplied request in the supplied phase using the * configured test engines to be used by the suite engine. * *

Applies {@linkplain org.junit.platform.launcher.EngineFilter engine * filters} and {@linkplain PostDiscoveryFilter post-discovery filters} and * {@linkplain TestDescriptor#prune() prunes} the resulting test tree. * * Note: The test descriptors in the discovery result can safely be used as * non-root descriptors. Engine-test descriptor entries are pruned from * the returned result. As such execution by * {@link EngineExecutionOrchestrator#execute(LauncherDiscoveryResult, EngineExecutionListener)} * will not emit start or emit events for engines without tests. */ public LauncherDiscoveryResult discover(LauncherDiscoveryRequest request, Phase phase, UniqueId parentId) { Map testEngines = discover(request, phase, parentId::appendEngine); LauncherDiscoveryResult result = new LauncherDiscoveryResult(testEngines, request.getConfigurationParameters()); return result.withRetainedEngines(TestDescriptor::containsTests); } private Map discover(LauncherDiscoveryRequest request, Phase phase, Function uniqueIdCreator) { LauncherDiscoveryListener listener = getLauncherDiscoveryListener(request); listener.launcherDiscoveryStarted(request); try { return discoverSafely(request, phase, listener, uniqueIdCreator); } finally { listener.launcherDiscoveryFinished(request); } } private Map discoverSafely(LauncherDiscoveryRequest request, Phase phase, LauncherDiscoveryListener listener, Function uniqueIdCreator) { Map testEngineDescriptors = new LinkedHashMap<>(); EngineFilterer engineFilterer = new EngineFilterer(request.getEngineFilters()); for (TestEngine testEngine : this.testEngines) { boolean engineIsExcluded = engineFilterer.isExcluded(testEngine); if (engineIsExcluded) { logger.debug(() -> String.format( "Test discovery for engine '%s' was skipped due to an EngineFilter in %s phase.", testEngine.getId(), phase)); continue; } logger.debug(() -> String.format("Discovering tests during Launcher %s phase in engine '%s'.", phase, testEngine.getId())); TestDescriptor rootDescriptor = discoverEngineRoot(testEngine, request, listener, uniqueIdCreator); testEngineDescriptors.put(testEngine, rootDescriptor); } engineFilterer.performSanityChecks(); List filters = new LinkedList<>(postDiscoveryFilters); filters.addAll(request.getPostDiscoveryFilters()); applyPostDiscoveryFilters(testEngineDescriptors, filters); prune(testEngineDescriptors); return testEngineDescriptors; } private TestDescriptor discoverEngineRoot(TestEngine testEngine, LauncherDiscoveryRequest request, LauncherDiscoveryListener listener, Function uniqueIdCreator) { UniqueId uniqueEngineId = uniqueIdCreator.apply(testEngine.getId()); try { listener.engineDiscoveryStarted(uniqueEngineId); TestDescriptor engineRoot = testEngine.discover(request, uniqueEngineId); discoveryResultValidator.validate(testEngine, engineRoot); listener.engineDiscoveryFinished(uniqueEngineId, EngineDiscoveryResult.successful()); return engineRoot; } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); String message = String.format("TestEngine with ID '%s' failed to discover tests", testEngine.getId()); JUnitException cause = new JUnitException(message, throwable); listener.engineDiscoveryFinished(uniqueEngineId, EngineDiscoveryResult.failed(cause)); return new EngineDiscoveryErrorDescriptor(uniqueEngineId, testEngine, cause); } } LauncherDiscoveryListener getLauncherDiscoveryListener(LauncherDiscoveryRequest discoveryRequest) { return ListenerRegistry.copyOf(launcherDiscoveryListenerRegistry) // .add(discoveryRequest.getDiscoveryListener()) // .getCompositeListener(); } private void applyPostDiscoveryFilters(Map testEngineDescriptors, List filters) { Filter postDiscoveryFilter = composeFilters(filters); Map> excludedTestDescriptorsByReason = new LinkedHashMap<>(); TestDescriptor.Visitor removeExcludedTestDescriptors = descriptor -> { FilterResult filterResult = postDiscoveryFilter.apply(descriptor); if (!descriptor.isRoot() && isExcluded(descriptor, filterResult)) { populateExclusionReasonInMap(filterResult.getReason(), descriptor, excludedTestDescriptorsByReason); descriptor.removeFromHierarchy(); } }; acceptInAllTestEngines(testEngineDescriptors, removeExcludedTestDescriptors); logTestDescriptorExclusionReasons(excludedTestDescriptorsByReason); } private void populateExclusionReasonInMap(Optional reason, TestDescriptor testDescriptor, Map> excludedTestDescriptorsByReason) { excludedTestDescriptorsByReason.computeIfAbsent(reason.orElse("Unknown"), list -> new LinkedList<>()).add( testDescriptor); } private void logTestDescriptorExclusionReasons(Map> excludedTestDescriptorsByReason) { excludedTestDescriptorsByReason.forEach((exclusionReason, testDescriptors) -> { String displayNames = testDescriptors.stream().map(TestDescriptor::getDisplayName).collect(joining(", ")); long containerCount = testDescriptors.stream().filter(TestDescriptor::isContainer).count(); long methodCount = testDescriptors.stream().filter(TestDescriptor::isTest).count(); logger.config(() -> String.format("%d containers and %d tests were %s", containerCount, methodCount, exclusionReason)); logger.debug( () -> String.format("The following containers and tests were %s: %s", exclusionReason, displayNames)); }); } /** * Prune all branches in the tree of {@link TestDescriptor TestDescriptors} * that do not have executable tests. * *

If a {@link TestEngine} ends up with no {@code TestDescriptors} after * pruning, it will not be removed. */ private void prune(Map testEngineDescriptors) { acceptInAllTestEngines(testEngineDescriptors, TestDescriptor::prune); } private boolean isExcluded(TestDescriptor descriptor, FilterResult filterResult) { return descriptor.getChildren().isEmpty() && filterResult.excluded(); } private void acceptInAllTestEngines(Map testEngineDescriptors, TestDescriptor.Visitor visitor) { testEngineDescriptors.values().forEach(descriptor -> descriptor.accept(visitor)); } public enum Phase { DISCOVERY, EXECUTION; @Override public String toString() { return name().toLowerCase(Locale.ENGLISH); } } } EngineDiscoveryResultValidator.java000066400000000000000000000062021455764576500376600ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.joining; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Queue; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; /** * Perform common validation checks on the result from the `discover()` method. * * @since 1.3 */ class EngineDiscoveryResultValidator { /** * Perform common validation checks. * * @throws org.junit.platform.commons.PreconditionViolationException if any check fails */ void validate(TestEngine testEngine, TestDescriptor root) { Preconditions.notNull(root, () -> String.format( "The discover() method for TestEngine with ID '%s' must return a non-null root TestDescriptor.", testEngine.getId())); Optional cyclicGraphInfo = getCyclicGraphInfo(root); Preconditions.condition(!cyclicGraphInfo.isPresent(), () -> String.format("The discover() method for TestEngine with ID '%s' returned a cyclic graph; %s", testEngine.getId(), cyclicGraphInfo.get())); } /** * @return non-empty {@link Optional} if the tree contains a cycle */ private Optional getCyclicGraphInfo(TestDescriptor root) { Map> visited = new HashMap<>(); visited.put(root.getUniqueId(), Optional.empty()); Queue queue = new ArrayDeque<>(); queue.add(root); while (!queue.isEmpty()) { TestDescriptor parent = queue.remove(); for (TestDescriptor child : parent.getChildren()) { UniqueId uid = child.getUniqueId(); if (visited.containsKey(uid)) { // id already known: cycle detected! List path1 = findPath(visited, uid); List path2 = findPath(visited, parent.getUniqueId()); path2.add(uid); return Optional.of(String.format("%s exists in at least two paths:\n(1) %s\n(2) %s", uid, formatted(path1), formatted(path2))); } else { visited.put(uid, Optional.of(parent.getUniqueId())); } if (child.isContainer()) { queue.add(child); } } } return Optional.empty(); } private String formatted(List path) { return path.stream().map(UniqueId::toString).collect(joining(" -> ")); } private static List findPath(Map> visited, UniqueId target) { List path = new ArrayList<>(); path.add(target); UniqueId current = target; while (visited.containsKey(current)) { Optional backTraced = visited.get(current); if (backTraced.isPresent()) { path.add(0, backTraced.get()); current = backTraced.get(); } else { break; } } return path; } } EngineExecutionOrchestrator.java000066400000000000000000000217521455764576500372160ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.launcher.LauncherConstants.DRY_RUN_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME; import static org.junit.platform.launcher.core.ListenerRegistry.forEngineExecutionListeners; import java.util.Optional; import java.util.function.Consumer; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Orchestrates test execution using the configured test engines. * * @since 1.7 */ @API(status = INTERNAL, since = "1.7", consumers = { "org.junit.platform.testkit", "org.junit.platform.suite.engine" }) public class EngineExecutionOrchestrator { private final ListenerRegistry listenerRegistry; public EngineExecutionOrchestrator() { this(ListenerRegistry.forTestExecutionListeners()); } EngineExecutionOrchestrator(ListenerRegistry listenerRegistry) { this.listenerRegistry = listenerRegistry; } void execute(InternalTestPlan internalTestPlan, TestExecutionListener... listeners) { ConfigurationParameters configurationParameters = internalTestPlan.getConfigurationParameters(); ListenerRegistry testExecutionListenerListeners = buildListenerRegistryForExecution( listeners); withInterceptedStreams(configurationParameters, testExecutionListenerListeners, testExecutionListener -> execute(internalTestPlan, EngineExecutionListener.NOOP, testExecutionListener)); } /** * Executes tests for the supplied {@linkplain LauncherDiscoveryResult * discoveryResult} and notifies the supplied {@linkplain * EngineExecutionListener engineExecutionListener} and * {@linkplain TestExecutionListener testExecutionListener} of execution * events. */ @API(status = INTERNAL, since = "1.9", consumers = { "org.junit.platform.suite.engine" }) public void execute(LauncherDiscoveryResult discoveryResult, EngineExecutionListener engineExecutionListener, TestExecutionListener testExecutionListener) { Preconditions.notNull(discoveryResult, "discoveryResult must not be null"); Preconditions.notNull(engineExecutionListener, "engineExecutionListener must not be null"); Preconditions.notNull(testExecutionListener, "testExecutionListener must not be null"); InternalTestPlan internalTestPlan = InternalTestPlan.from(discoveryResult); execute(internalTestPlan, engineExecutionListener, testExecutionListener); } private void execute(InternalTestPlan internalTestPlan, EngineExecutionListener parentEngineExecutionListener, TestExecutionListener testExecutionListener) { internalTestPlan.markStarted(); // Do not directly pass the internal test plan to test execution listeners. // Hyrum's Law indicates that someone will eventually come to depend on it. TestPlan testPlan = internalTestPlan.getDelegate(); LauncherDiscoveryResult discoveryResult = internalTestPlan.getDiscoveryResult(); testExecutionListener.testPlanExecutionStarted(testPlan); if (isDryRun(internalTestPlan)) { dryRun(testPlan, testExecutionListener); } else { execute(discoveryResult, buildEngineExecutionListener(parentEngineExecutionListener, testExecutionListener, testPlan)); } testExecutionListener.testPlanExecutionFinished(testPlan); } private Boolean isDryRun(InternalTestPlan internalTestPlan) { return internalTestPlan.getConfigurationParameters().getBoolean(DRY_RUN_PROPERTY_NAME).orElse(false); } private void dryRun(TestPlan testPlan, TestExecutionListener listener) { testPlan.accept(new TestPlan.Visitor() { @Override public void preVisitContainer(TestIdentifier testIdentifier) { listener.executionStarted(testIdentifier); } @Override public void visit(TestIdentifier testIdentifier) { if (!testIdentifier.isContainer()) { listener.executionSkipped(testIdentifier, "JUnit Platform dry-run mode is enabled"); } } @Override public void postVisitContainer(TestIdentifier testIdentifier) { listener.executionFinished(testIdentifier, TestExecutionResult.successful()); } }); } private static EngineExecutionListener buildEngineExecutionListener( EngineExecutionListener parentEngineExecutionListener, TestExecutionListener testExecutionListener, TestPlan testPlan) { ListenerRegistry engineExecutionListenerRegistry = forEngineExecutionListeners(); engineExecutionListenerRegistry.add(new ExecutionListenerAdapter(testPlan, testExecutionListener)); engineExecutionListenerRegistry.add(parentEngineExecutionListener); return engineExecutionListenerRegistry.getCompositeListener(); } private void withInterceptedStreams(ConfigurationParameters configurationParameters, ListenerRegistry listenerRegistry, Consumer action) { TestExecutionListener testExecutionListener = listenerRegistry.getCompositeListener(); Optional streamInterceptingTestExecutionListener = StreamInterceptingTestExecutionListener.create( configurationParameters, testExecutionListener::reportingEntryPublished); streamInterceptingTestExecutionListener.ifPresent(listenerRegistry::add); try { action.accept(listenerRegistry.getCompositeListener()); } finally { streamInterceptingTestExecutionListener.ifPresent(StreamInterceptingTestExecutionListener::unregister); } } /** * Executes tests for the supplied {@linkplain LauncherDiscoveryResult * discovery results} and notifies the supplied {@linkplain * EngineExecutionListener listener} of execution events. */ @API(status = INTERNAL, since = "1.7", consumers = { "org.junit.platform.testkit" }) public void execute(LauncherDiscoveryResult discoveryResult, EngineExecutionListener engineExecutionListener) { Preconditions.notNull(discoveryResult, "discoveryResult must not be null"); Preconditions.notNull(engineExecutionListener, "engineExecutionListener must not be null"); ConfigurationParameters configurationParameters = discoveryResult.getConfigurationParameters(); EngineExecutionListener listener = selectExecutionListener(engineExecutionListener, configurationParameters); for (TestEngine testEngine : discoveryResult.getTestEngines()) { TestDescriptor engineDescriptor = discoveryResult.getEngineTestDescriptor(testEngine); if (engineDescriptor instanceof EngineDiscoveryErrorDescriptor) { listener.executionStarted(engineDescriptor); listener.executionFinished(engineDescriptor, TestExecutionResult.failed(((EngineDiscoveryErrorDescriptor) engineDescriptor).getCause())); } else { execute(engineDescriptor, listener, configurationParameters, testEngine); } } } private static EngineExecutionListener selectExecutionListener(EngineExecutionListener engineExecutionListener, ConfigurationParameters configurationParameters) { boolean stackTracePruningEnabled = configurationParameters.getBoolean(STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME) // .orElse(true); if (stackTracePruningEnabled) { return new StackTracePruningEngineExecutionListener(engineExecutionListener); } return engineExecutionListener; } private ListenerRegistry buildListenerRegistryForExecution( TestExecutionListener... listeners) { if (listeners.length == 0) { return this.listenerRegistry; } return ListenerRegistry.copyOf(this.listenerRegistry).addAll(listeners); } private void execute(TestDescriptor engineDescriptor, EngineExecutionListener listener, ConfigurationParameters configurationParameters, TestEngine testEngine) { OutcomeDelayingEngineExecutionListener delayingListener = new OutcomeDelayingEngineExecutionListener(listener, engineDescriptor); try { testEngine.execute(new ExecutionRequest(engineDescriptor, delayingListener, configurationParameters)); delayingListener.reportEngineOutcome(); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); delayingListener.reportEngineFailure(new JUnitException( String.format("TestEngine with ID '%s' failed to execute tests", testEngine.getId()), throwable)); } } } EngineFilterer.java000066400000000000000000000062101455764576500344170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toCollection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.EngineFilter; class EngineFilterer { private static final Logger LOGGER = LoggerFactory.getLogger(EngineFilterer.class); private final List engineFilters; private final Map checkedTestEngines = new HashMap<>(); EngineFilterer(List engineFilters) { this.engineFilters = engineFilters; } boolean isExcluded(TestEngine testEngine) { boolean excluded = engineFilters.stream() // .map(engineFilter -> engineFilter.apply(testEngine)) // .anyMatch(FilterResult::excluded); checkedTestEngines.put(testEngine, excluded); return excluded; } void performSanityChecks() { checkNoUnmatchedIncludeFilter(); warnIfAllEnginesExcluded(); } private void warnIfAllEnginesExcluded() { if (!checkedTestEngines.isEmpty() && checkedTestEngines.values().stream().allMatch(excluded -> excluded)) { LOGGER.warn(() -> "All TestEngines were excluded by EngineFilters.\n" + getStateDescription()); } } private void checkNoUnmatchedIncludeFilter() { SortedSet unmatchedEngineIdsOfIncludeFilters = getUnmatchedEngineIdsOfIncludeFilters(); if (!unmatchedEngineIdsOfIncludeFilters.isEmpty()) { throw new JUnitException("No TestEngine ID matched the following include EngineFilters: " + unmatchedEngineIdsOfIncludeFilters + ".\n" // + "Please fix/remove the filter or add the engine.\n" // + getStateDescription()); } } private SortedSet getUnmatchedEngineIdsOfIncludeFilters() { return engineFilters.stream() // .filter(EngineFilter::isIncludeFilter) // .filter(engineFilter -> checkedTestEngines.keySet().stream() // .map(engineFilter::apply) // .noneMatch(FilterResult::included)) // .flatMap(engineFilter -> engineFilter.getEngineIds().stream()) // .collect(toCollection(TreeSet::new)); } private String getStateDescription() { return getRegisteredEnginesDescription() + "\n" + getRegisteredFiltersDescription(); } private String getRegisteredEnginesDescription() { return TestEngineFormatter.format("Registered TestEngines", checkedTestEngines.keySet()); } private String getRegisteredFiltersDescription() { return "Registered EngineFilters:" + engineFilters.stream() // .map(Objects::toString) // .collect(joining("\n- ", "\n- ", "")); } } EngineIdValidator.java000066400000000000000000000051261455764576500350520ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.HashSet; import java.util.Set; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.TestEngine; /** * @since 1.7 */ class EngineIdValidator { private EngineIdValidator() { } static Iterable validate(Iterable testEngines) { Set ids = new HashSet<>(); for (TestEngine testEngine : testEngines) { // check usage of reserved id prefix if (!validateReservedIds(testEngine)) { getLogger().warn(() -> String.format( "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '%s'", testEngine.getId())); } // check uniqueness if (!ids.add(testEngine.getId())) { throw new JUnitException(String.format( "Cannot create Launcher for multiple engines with the same ID '%s'.", testEngine.getId())); } } return testEngines; } private static Logger getLogger() { // Not a constant to avoid problems with building GraalVM native images return LoggerFactory.getLogger(EngineIdValidator.class); } // https://github.com/junit-team/junit5/issues/1557 private static boolean validateReservedIds(TestEngine testEngine) { String engineId = testEngine.getId(); if (!engineId.startsWith("junit-")) { return true; } if (engineId.equals("junit-jupiter")) { validateWellKnownClassName(testEngine, "org.junit.jupiter.engine.JupiterTestEngine"); return true; } if (engineId.equals("junit-vintage")) { validateWellKnownClassName(testEngine, "org.junit.vintage.engine.VintageTestEngine"); return true; } if (engineId.equals("junit-platform-suite")) { validateWellKnownClassName(testEngine, "org.junit.platform.suite.engine.SuiteTestEngine"); return true; } return false; } private static void validateWellKnownClassName(TestEngine testEngine, String expectedClassName) { String actualClassName = testEngine.getClass().getName(); if (actualClassName.equals(expectedClassName)) { return; } throw new JUnitException( String.format("Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.", actualClassName, testEngine.getId())); } } ExecutionListenerAdapter.java000066400000000000000000000046161455764576500364770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * An {@code ExecutionListenerAdapter} adapts a {@link TestPlan} and a corresponding * {@link TestExecutionListener} to the {@link EngineExecutionListener} API. * * @since 1.0 */ class ExecutionListenerAdapter implements EngineExecutionListener { private final TestPlan testPlan; private final TestExecutionListener testExecutionListener; ExecutionListenerAdapter(TestPlan testPlan, TestExecutionListener testExecutionListener) { this.testPlan = testPlan; this.testExecutionListener = testExecutionListener; } @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { TestIdentifier testIdentifier = TestIdentifier.from(testDescriptor); this.testPlan.addInternal(testIdentifier); this.testExecutionListener.dynamicTestRegistered(testIdentifier); } @Override public void executionStarted(TestDescriptor testDescriptor) { this.testExecutionListener.executionStarted(getTestIdentifier(testDescriptor)); } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { this.testExecutionListener.executionSkipped(getTestIdentifier(testDescriptor), reason); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { this.testExecutionListener.executionFinished(getTestIdentifier(testDescriptor), testExecutionResult); } @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { this.testExecutionListener.reportingEntryPublished(getTestIdentifier(testDescriptor), entry); } private TestIdentifier getTestIdentifier(TestDescriptor testDescriptor) { return this.testPlan.getTestIdentifier(testDescriptor.getUniqueId()); } } InterceptingLauncher.java000066400000000000000000000027111455764576500356340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * @since 1.10 */ class InterceptingLauncher extends DelegatingLauncher { private final LauncherInterceptor interceptor; InterceptingLauncher(Launcher delegate, LauncherInterceptor interceptor) { super(delegate); this.interceptor = interceptor; } @Override public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { return interceptor.intercept(() -> super.discover(launcherDiscoveryRequest)); } @Override public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { interceptor.intercept(() -> { super.execute(launcherDiscoveryRequest, listeners); return null; }); } @Override public void execute(TestPlan testPlan, TestExecutionListener... listeners) { interceptor.intercept(() -> { super.execute(testPlan, listeners); return null; }); } } InternalTestPlan.java000066400000000000000000000062531455764576500347530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.4 */ class InternalTestPlan extends TestPlan { private final AtomicBoolean executionStarted = new AtomicBoolean(false); private final LauncherDiscoveryResult discoveryResult; private final TestPlan delegate; static InternalTestPlan from(LauncherDiscoveryResult discoveryResult) { TestPlan delegate = TestPlan.from(discoveryResult.getEngineTestDescriptors(), discoveryResult.getConfigurationParameters()); return new InternalTestPlan(discoveryResult, delegate); } private InternalTestPlan(LauncherDiscoveryResult discoveryResult, TestPlan delegate) { super(delegate.containsTests(), delegate.getConfigurationParameters()); this.discoveryResult = discoveryResult; this.delegate = delegate; } void markStarted() { if (!executionStarted.compareAndSet(false, true)) { throw new PreconditionViolationException("TestPlan must only be executed once"); } } LauncherDiscoveryResult getDiscoveryResult() { return discoveryResult; } public TestPlan getDelegate() { return delegate; } @Override @SuppressWarnings("deprecation") public void add(TestIdentifier testIdentifier) { delegate.add(testIdentifier); } @Override public void addInternal(TestIdentifier testIdentifier) { delegate.addInternal(testIdentifier); } @Override public Set getRoots() { return delegate.getRoots(); } @Override public Optional getParent(TestIdentifier child) { return delegate.getParent(child); } @Override public Set getChildren(TestIdentifier parent) { return delegate.getChildren(parent); } @SuppressWarnings("deprecation") @Override public Set getChildren(String parentId) { return delegate.getChildren(parentId); } @Override public Set getChildren(UniqueId parentId) { return delegate.getChildren(parentId); } @SuppressWarnings("deprecation") @Override public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { return delegate.getTestIdentifier(uniqueId); } @Override public TestIdentifier getTestIdentifier(UniqueId uniqueId) { return delegate.getTestIdentifier(uniqueId); } @Override public long countTestIdentifiers(Predicate predicate) { return delegate.countTestIdentifiers(predicate); } @Override public Set getDescendants(TestIdentifier parent) { return delegate.getDescendants(parent); } @Override public boolean containsTests() { return delegate.containsTests(); } } IterationOrder.java000066400000000000000000000015311455764576500344500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.util.List; import java.util.function.Consumer; enum IterationOrder { ORIGINAL { @Override void forEach(List listeners, Consumer action) { listeners.forEach(action); } }, REVERSED { @Override void forEach(List listeners, Consumer action) { forEachInReverseOrder(listeners, action); } }; abstract void forEach(List listeners, Consumer action); } LauncherConfig.java000066400000000000000000000303741455764576500344140ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.TestExecutionListener; /** * {@code LauncherConfig} defines the configuration API for creating * {@link Launcher} instances via the {@link LauncherFactory}. * *

Example

* *
 * LauncherConfig launcherConfig = LauncherConfig.builder()
 *   .enableTestEngineAutoRegistration(false)
 *   .enableTestExecutionListenerAutoRegistration(false)
 *   .addTestEngines(new CustomTestEngine())
 *   .addTestExecutionListeners(new CustomTestExecutionListener())
 *   .build();
 *
 * Launcher launcher = LauncherFactory.create(launcherConfig);
 * LauncherDiscoveryRequest discoveryRequest = ...
 * launcher.execute(discoveryRequest);
 * 
* * @since 1.3 * @see #builder() * @see Launcher * @see LauncherFactory */ @API(status = STABLE, since = "1.7") public interface LauncherConfig { /** * The default {@code LauncherConfig} which uses automatic registration for * test engines, supported listeners, and post-discovery filters. */ LauncherConfig DEFAULT = builder().build(); /** * Determine if test engines should be discovered at runtime using the * {@link java.util.ServiceLoader ServiceLoader} mechanism and * automatically registered. * * @return {@code true} if test engines should be automatically registered */ boolean isTestEngineAutoRegistrationEnabled(); /** * Determine if launcher session listeners should be discovered at runtime * using the {@link java.util.ServiceLoader ServiceLoader} mechanism and * automatically registered. * * @return {@code true} if launcher session listeners should be * automatically registered * @since 1.8 */ @API(status = STABLE, since = "1.10") boolean isLauncherSessionListenerAutoRegistrationEnabled(); /** * Determine if launcher discovery listeners should be discovered at runtime * using the {@link java.util.ServiceLoader ServiceLoader} mechanism and * automatically registered. * * @return {@code true} if launcher discovery listeners should be * automatically registered * @since 1.8 */ @API(status = STABLE, since = "1.10") boolean isLauncherDiscoveryListenerAutoRegistrationEnabled(); /** * Determine if test execution listeners should be discovered at runtime * using the {@link java.util.ServiceLoader ServiceLoader} mechanism and * automatically registered. * * @return {@code true} if test execution listeners should be automatically * registered */ boolean isTestExecutionListenerAutoRegistrationEnabled(); /** * Determine if post discovery filters should be discovered at runtime * using the {@link java.util.ServiceLoader ServiceLoader} mechanism and * automatically registered. * * @return {@code true} if post discovery filters should be automatically * registered * @since 1.7 */ @API(status = STABLE, since = "1.10") boolean isPostDiscoveryFilterAutoRegistrationEnabled(); /** * Get the collection of additional test engines that should be added to * the {@link Launcher}. * * @return the collection of additional test engines; never {@code null} but * potentially empty */ Collection getAdditionalTestEngines(); /** * Get the collection of additional launcher session listeners that should * be added to the {@link Launcher}. * * @return the collection of additional launcher session listeners; never * {@code null} but potentially empty * @since 1.8 */ @API(status = STABLE, since = "1.10") Collection getAdditionalLauncherSessionListeners(); /** * Get the collection of additional launcher discovery listeners that should * be added to the {@link Launcher}. * * @return the collection of additional launcher discovery listeners; never * {@code null} but potentially empty * @since 1.8 */ @API(status = STABLE, since = "1.10") Collection getAdditionalLauncherDiscoveryListeners(); /** * Get the collection of additional test execution listeners that should be * added to the {@link Launcher}. * * @return the collection of additional test execution listeners; never * {@code null} but potentially empty */ Collection getAdditionalTestExecutionListeners(); /** * Get the collection of additional post discovery filters that should be * added to the {@link Launcher}. * * @return the collection of additional post discovery filters; never * {@code null} but potentially empty * @since 1.7 */ @API(status = STABLE, since = "1.10") Collection getAdditionalPostDiscoveryFilters(); /** * Create a new {@link LauncherConfig.Builder}. * * @return a new builder; never {@code null} */ static Builder builder() { return new Builder(); } /** * Builder API for {@link LauncherConfig}. */ class Builder { private boolean engineAutoRegistrationEnabled = true; private boolean launcherSessionListenerAutoRegistrationEnabled = true; private boolean launcherDiscoveryListenerAutoRegistrationEnabled = true; private boolean testExecutionListenerAutoRegistrationEnabled = true; private boolean postDiscoveryFilterAutoRegistrationEnabled = true; private final Collection engines = new LinkedHashSet<>(); private final Collection sessionListeners = new LinkedHashSet<>(); private final Collection discoveryListeners = new LinkedHashSet<>(); private final Collection executionListeners = new LinkedHashSet<>(); private final Collection postDiscoveryFilters = new LinkedHashSet<>(); private Builder() { /* no-op */ } /** * Configure the auto-registration flag for launcher session * listeners. * *

Defaults to {@code true}. * * @param enabled {@code true} if launcher session listeners should be * automatically registered * @return this builder for method chaining * @since 1.8 */ @API(status = STABLE, since = "1.10") public Builder enableLauncherSessionListenerAutoRegistration(boolean enabled) { this.launcherSessionListenerAutoRegistrationEnabled = enabled; return this; } /** * Configure the auto-registration flag for launcher discovery * listeners. * *

Defaults to {@code true}. * * @param enabled {@code true} if launcher discovery listeners should be * automatically registered * @return this builder for method chaining * @since 1.8 */ @API(status = STABLE, since = "1.10") public Builder enableLauncherDiscoveryListenerAutoRegistration(boolean enabled) { this.launcherDiscoveryListenerAutoRegistrationEnabled = enabled; return this; } /** * Configure the auto-registration flag for test execution listeners. * *

Defaults to {@code true}. * * @param enabled {@code true} if test execution listeners should be * automatically registered * @return this builder for method chaining */ public Builder enableTestExecutionListenerAutoRegistration(boolean enabled) { this.testExecutionListenerAutoRegistrationEnabled = enabled; return this; } /** * Configure the auto-registration flag for test engines. * *

Defaults to {@code true}. * * @param enabled {@code true} if test engines should be automatically * registered * @return this builder for method chaining */ public Builder enableTestEngineAutoRegistration(boolean enabled) { this.engineAutoRegistrationEnabled = enabled; return this; } /** * Configure the auto-registration flag for post discovery filters. * *

Defaults to {@code true}. * * @param enabled {@code true} if post discovery filters should be automatically * registered * @return this builder for method chaining * @since 1.7 */ @API(status = STABLE, since = "1.10") public Builder enablePostDiscoveryFilterAutoRegistration(boolean enabled) { this.postDiscoveryFilterAutoRegistrationEnabled = enabled; return this; } /** * Add all of the supplied test engines to the configuration. * * @param engines additional test engines to register; never {@code null} * or containing {@code null} * @return this builder for method chaining */ public Builder addTestEngines(TestEngine... engines) { Preconditions.notNull(engines, "TestEngine array must not be null"); Preconditions.containsNoNullElements(engines, "TestEngine array must not contain null elements"); Collections.addAll(this.engines, engines); return this; } /** * Add all of the supplied launcher session listeners to the configuration. * * @param listeners additional launcher session listeners to register; * never {@code null} or containing {@code null} * @return this builder for method chaining */ public Builder addLauncherSessionListeners(LauncherSessionListener... listeners) { Preconditions.notNull(listeners, "LauncherSessionListener array must not be null"); Preconditions.containsNoNullElements(listeners, "LauncherSessionListener array must not contain null elements"); Collections.addAll(this.sessionListeners, listeners); return this; } /** * Add all of the supplied launcher discovery listeners to the configuration. * * @param listeners additional launcher discovery listeners to register; * never {@code null} or containing {@code null} * @return this builder for method chaining */ public Builder addLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { Preconditions.notNull(listeners, "LauncherDiscoveryListener array must not be null"); Preconditions.containsNoNullElements(listeners, "LauncherDiscoveryListener array must not contain null elements"); Collections.addAll(this.discoveryListeners, listeners); return this; } /** * Add all of the supplied test execution listeners to the configuration. * * @param listeners additional test execution listeners to register; * never {@code null} or containing {@code null} * @return this builder for method chaining */ public Builder addTestExecutionListeners(TestExecutionListener... listeners) { Preconditions.notNull(listeners, "TestExecutionListener array must not be null"); Preconditions.containsNoNullElements(listeners, "TestExecutionListener array must not contain null elements"); Collections.addAll(this.executionListeners, listeners); return this; } /** * Add all of the supplied {@code filters} to the configuration. * * @param filters additional post discovery filters to register; * never {@code null} or containing {@code null} * @return this builder for method chaining * @since 1.7 */ @API(status = STABLE, since = "1.10") public Builder addPostDiscoveryFilters(PostDiscoveryFilter... filters) { Preconditions.notNull(filters, "PostDiscoveryFilter array must not be null"); Preconditions.containsNoNullElements(filters, "PostDiscoveryFilter array must not contain null elements"); Collections.addAll(this.postDiscoveryFilters, filters); return this; } /** * Build the {@link LauncherConfig} that has been configured via this * builder. */ public LauncherConfig build() { return new DefaultLauncherConfig(this.engineAutoRegistrationEnabled, this.launcherSessionListenerAutoRegistrationEnabled, this.launcherDiscoveryListenerAutoRegistrationEnabled, this.testExecutionListenerAutoRegistrationEnabled, this.postDiscoveryFilterAutoRegistrationEnabled, this.engines, this.sessionListeners, this.discoveryListeners, this.executionListeners, this.postDiscoveryFilters); } } } LauncherConfigurationParameters.java000066400000000000000000000174011455764576500400360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.ConfigurationParameters; /** * @since 1.0 */ class LauncherConfigurationParameters implements ConfigurationParameters { private static final Logger logger = LoggerFactory.getLogger(LauncherConfigurationParameters.class); static Builder builder() { return new Builder(); } private final List providers; private LauncherConfigurationParameters(List providers) { this.providers = providers; } @Override public Optional get(String key) { return Optional.ofNullable(getProperty(key)); } @Override public Optional getBoolean(String key) { return get(key).map(Boolean::parseBoolean); } @Override @SuppressWarnings("deprecation") public int size() { return providers.stream() // .mapToInt(ParameterProvider::size) // .sum(); } @Override public Set keySet() { return providers.stream().map(ParameterProvider::keySet).flatMap(Collection::stream).collect( Collectors.toSet()); } private String getProperty(String key) { Preconditions.notBlank(key, "key must not be null or blank"); return providers.stream() // .map(parameterProvider -> parameterProvider.getValue(key)) // .filter(Objects::nonNull) // .findFirst() // .orElse(null); } @Override public String toString() { return new ToStringBuilder(this) // .append("lookups", providers) // .toString(); } static final class Builder { private final Map explicitParameters = new HashMap<>(); private boolean implicitProvidersEnabled = true; private String configFileName = ConfigurationParameters.CONFIG_FILE_NAME; private ConfigurationParameters parentConfigurationParameters; private Builder() { } Builder explicitParameters(Map parameters) { Preconditions.notNull(parameters, "configuration parameters must not be null"); explicitParameters.putAll(parameters); return this; } Builder enableImplicitProviders(boolean enabled) { this.implicitProvidersEnabled = enabled; return this; } Builder configFileName(String configFileName) { Preconditions.notBlank(configFileName, "configFileName must not be null or blank"); this.configFileName = configFileName; return this; } Builder parentConfigurationParameters(ConfigurationParameters parameters) { Preconditions.notNull(parameters, "parent configuration parameters must not be null"); this.parentConfigurationParameters = parameters; return this; } LauncherConfigurationParameters build() { List parameterProviders = new ArrayList<>(); if (!explicitParameters.isEmpty()) { parameterProviders.add(ParameterProvider.explicit(explicitParameters)); } if (parentConfigurationParameters != null) { parameterProviders.add(ParameterProvider.inherited(parentConfigurationParameters)); } if (implicitProvidersEnabled) { parameterProviders.add(ParameterProvider.systemProperties()); parameterProviders.add(ParameterProvider.propertiesFile(configFileName)); } return new LauncherConfigurationParameters(parameterProviders); } } private interface ParameterProvider { String getValue(String key); default int size() { return 0; } Set keySet(); static ParameterProvider explicit(Map configParams) { return new ParameterProvider() { @Override public String getValue(String key) { return configParams.get(key); } @Override public int size() { return configParams.size(); } @Override public Set keySet() { return configParams.keySet(); } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder("explicit"); configParams.forEach(builder::append); return builder.toString(); } }; } static ParameterProvider systemProperties() { return new ParameterProvider() { @Override public String getValue(String key) { try { return System.getProperty(key); } catch (Exception ignore) { return null; } } @Override public Set keySet() { return System.getProperties().stringPropertyNames(); } @Override public String toString() { return "systemProperties [...]"; } }; } static ParameterProvider propertiesFile(String configFileName) { Preconditions.notBlank(configFileName, "configFileName must not be null or blank"); Properties properties = loadClasspathResource(configFileName.trim()); return new ParameterProvider() { @Override public String getValue(String key) { return properties.getProperty(key); } @Override public Set keySet() { return properties.stringPropertyNames(); } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder("propertiesFile"); properties.stringPropertyNames().forEach(key -> builder.append(key, getValue(key))); return builder.toString(); } }; } static ParameterProvider inherited(ConfigurationParameters configParams) { return new ParameterProvider() { @Override public String getValue(String key) { return configParams.get(key).orElse(null); } @Override @SuppressWarnings("deprecation") public int size() { return configParams.size(); } @Override public Set keySet() { return configParams.keySet(); } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder("inherited"); builder.append("parent", configParams); return builder.toString(); } }; } } private static Properties loadClasspathResource(String configFileName) { Properties props = new Properties(); try { ClassLoader classLoader = ClassLoaderUtils.getDefaultClassLoader(); Set resources = new LinkedHashSet<>(Collections.list(classLoader.getResources(configFileName))); if (!resources.isEmpty()) { if (resources.size() > 1) { logger.warn(() -> String.format( "Discovered %d '%s' configuration files in the classpath; only the first will be used.", resources.size(), configFileName)); } URL configFileUrl = resources.iterator().next(); // same as List#get(0) logger.config(() -> String.format( "Loading JUnit Platform configuration parameters from classpath resource [%s].", configFileUrl)); URLConnection urlConnection = configFileUrl.openConnection(); urlConnection.setUseCaches(false); try (InputStream inputStream = urlConnection.getInputStream()) { props.load(inputStream); } } } catch (Exception ex) { logger.warn(ex, () -> String.format( "Failed to load JUnit Platform configuration parameters from classpath resource [%s].", configFileName)); } return props; } } LauncherDiscoveryRequestBuilder.java000066400000000000000000000322571455764576500400400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.Filter; import org.junit.platform.launcher.EngineFilter; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.core.LauncherConfigurationParameters.Builder; import org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners; /** * The {@code LauncherDiscoveryRequestBuilder} provides a light-weight DSL for * generating a {@link LauncherDiscoveryRequest}. * *

Example

* *
 * import static org.junit.platform.engine.discovery.DiscoverySelectors.*;
 * import static org.junit.platform.engine.discovery.ClassNameFilter.*;
 * import static org.junit.platform.launcher.EngineFilter.*;
 * import static org.junit.platform.launcher.TagFilter.*;
 *
 * // ...
 *
 *   LauncherDiscoveryRequestBuilder.request()
 *     .selectors(
 *        selectPackage("org.example.user"),
 *        selectClass("org.example.payment.PaymentTests"),
 *        selectClass(ShippingTests.class),
 *        selectMethod("org.example.order.OrderTests#test1"),
 *        selectMethod("org.example.order.OrderTests#test2()"),
 *        selectMethod("org.example.order.OrderTests#test3(java.lang.String)"),
 *        selectMethod("org.example.order.OrderTests", "test4"),
 *        selectMethod(OrderTests.class, "test5"),
 *        selectMethod(OrderTests.class, testMethod),
 *        selectClasspathRoots(Collections.singleton(new File("/my/local/path1"))),
 *        selectUniqueId("unique-id-1"),
 *        selectUniqueId("unique-id-2")
 *     )
 *     .filters(
 *        includeEngines("junit-jupiter", "spek"),
 *        // excludeEngines("junit-vintage"),
 *        includeTags("fast"),
 *        // excludeTags("slow"),
 *        includeClassNamePatterns(".*Test[s]?")
 *        // includeClassNamePatterns("org\.example\.tests.*")
 *     )
 *     .configurationParameter("key1", "value1")
 *     .configurationParameters(configParameterMap)
 *     .build();
 * 
* * @since 1.0 * @see org.junit.platform.engine.discovery.DiscoverySelectors * @see org.junit.platform.engine.discovery.ClassNameFilter * @see org.junit.platform.launcher.EngineFilter * @see org.junit.platform.launcher.TagFilter */ @API(status = STABLE, since = "1.0") public final class LauncherDiscoveryRequestBuilder { /** * Property name used to set the default discovery listener that is added to all : {@value} * *

Supported Values

* *

Supported values are {@code "logging"} and {@code "abortOnFailure"}. * *

If not specified, the default is {@value #DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_VALUE}. */ public static final String DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME = "junit.platform.discovery.listener.default"; private static final String DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_VALUE = "abortOnFailure"; private final List selectors = new ArrayList<>(); private final List engineFilters = new ArrayList<>(); private final List> discoveryFilters = new ArrayList<>(); private final List postDiscoveryFilters = new ArrayList<>(); private final Map configurationParameters = new HashMap<>(); private final List discoveryListeners = new ArrayList<>(); private boolean implicitConfigurationParametersEnabled = true; private ConfigurationParameters parentConfigurationParameters; /** * Create a new {@code LauncherDiscoveryRequestBuilder}. * * @return a new builder */ public static LauncherDiscoveryRequestBuilder request() { return new LauncherDiscoveryRequestBuilder(); } /** * @deprecated Use {@link #request()} */ @API(status = DEPRECATED, since = "1.8") @Deprecated public LauncherDiscoveryRequestBuilder() { } /** * Add all of the supplied {@code selectors} to the request. * * @param selectors the {@code DiscoverySelectors} to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder selectors(DiscoverySelector... selectors) { Preconditions.notNull(selectors, "selectors array must not be null"); selectors(Arrays.asList(selectors)); return this; } /** * Add all of the supplied {@code selectors} to the request. * * @param selectors the {@code DiscoverySelectors} to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder selectors(List selectors) { Preconditions.notNull(selectors, "selectors list must not be null"); Preconditions.containsNoNullElements(selectors, "individual selectors must not be null"); this.selectors.addAll(selectors); return this; } /** * Add all of the supplied {@code filters} to the request. * *

The {@code filters} are combined using AND semantics, i.e. all of them * have to include a resource for it to end up in the test plan. * *

Warning: be cautious when registering multiple competing * {@link EngineFilter#includeEngines include} {@code EngineFilters} or multiple * competing {@link EngineFilter#excludeEngines exclude} {@code EngineFilters} * for the same discovery request since doing so will likely lead to * undesirable results (i.e., zero engines being active). * * @param filters the {@code Filter}s to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder filters(Filter... filters) { Preconditions.notNull(filters, "filters array must not be null"); Preconditions.containsNoNullElements(filters, "individual filters must not be null"); Arrays.stream(filters).forEach(this::storeFilter); return this; } /** * Add the supplied configuration parameter to the request. * * @param key the configuration parameter key under which to store the * value; never {@code null} or blank * @param value the value to store * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder configurationParameter(String key, String value) { Preconditions.notBlank(key, "configuration parameter key must not be null or blank"); this.configurationParameters.put(key, value); return this; } /** * Add all of the supplied configuration parameters to the request. * * @param configurationParameters the map of configuration parameters to add; * never {@code null} * @return this builder for method chaining * @see #configurationParameter(String, String) */ public LauncherDiscoveryRequestBuilder configurationParameters(Map configurationParameters) { Preconditions.notNull(configurationParameters, "configuration parameters map must not be null"); configurationParameters.forEach(this::configurationParameter); return this; } /** * Set the parent configuration parameters to use for the request. * *

Any explicit configuration parameters configured via * {@link #configurationParameter(String, String)} or * {@link #configurationParameters(Map)} takes precedence over the supplied * configuration parameters. * * @param configurationParameters the parent instance to be used for looking * up configuration parameters that have not been explicitly configured; * never {@code null} * @since 1.8 * @see #configurationParameter(String, String) * @see #configurationParameters(Map) */ @API(status = STABLE, since = "1.10") public LauncherDiscoveryRequestBuilder parentConfigurationParameters( ConfigurationParameters configurationParameters) { Preconditions.notNull(configurationParameters, "parent configuration parameters must not be null"); this.parentConfigurationParameters = configurationParameters; return this; } /** * Add all of the supplied discovery listeners to the request. * *

In addition to the {@linkplain LauncherDiscoveryListener listeners} * registered using this method, this builder will add a default listener * to this request that can be specified using the * {@value #DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME} * configuration parameter. * * @param listeners the {@code LauncherDiscoveryListeners} to add; never * {@code null} * @return this builder for method chaining * @since 1.6 * @see LauncherDiscoveryListener * @see LauncherDiscoveryListeners * @see LauncherDiscoveryRequestBuilder#DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME */ @API(status = STABLE, since = "1.10") public LauncherDiscoveryRequestBuilder listeners(LauncherDiscoveryListener... listeners) { Preconditions.notNull(listeners, "discovery listener array must not be null"); Preconditions.containsNoNullElements(listeners, "individual discovery listeners must not be null"); this.discoveryListeners.addAll(Arrays.asList(listeners)); return this; } /** * Configure whether implicit configuration parameters should be considered. * *

By default, in addition to those parameters that are passed explicitly * to this builder, configuration parameters are read from system properties * and from the {@code junit-platform.properties} classpath resource. * Passing {@code false} to this method, disables the latter two sources so * that only explicit configuration parameters are taken into account. * * @since 1.7 * @see #configurationParameter(String, String) * @see #configurationParameters(Map) */ @API(status = STABLE, since = "1.10") public LauncherDiscoveryRequestBuilder enableImplicitConfigurationParameters(boolean enabled) { this.implicitConfigurationParametersEnabled = enabled; return this; } private void storeFilter(Filter filter) { if (filter instanceof EngineFilter) { this.engineFilters.add((EngineFilter) filter); } else if (filter instanceof PostDiscoveryFilter) { this.postDiscoveryFilters.add((PostDiscoveryFilter) filter); } else if (filter instanceof DiscoveryFilter) { this.discoveryFilters.add((DiscoveryFilter) filter); } else { throw new PreconditionViolationException( String.format("Filter [%s] must implement %s, %s, or %s.", filter, EngineFilter.class.getSimpleName(), PostDiscoveryFilter.class.getSimpleName(), DiscoveryFilter.class.getSimpleName())); } } /** * Build the {@link LauncherDiscoveryRequest} that has been configured via * this builder. */ public LauncherDiscoveryRequest build() { LauncherConfigurationParameters launcherConfigurationParameters = buildLauncherConfigurationParameters(); LauncherDiscoveryListener discoveryListener = getLauncherDiscoveryListener(launcherConfigurationParameters); return new DefaultDiscoveryRequest(this.selectors, this.engineFilters, this.discoveryFilters, this.postDiscoveryFilters, launcherConfigurationParameters, discoveryListener); } private LauncherConfigurationParameters buildLauncherConfigurationParameters() { Builder builder = LauncherConfigurationParameters.builder() // .explicitParameters(this.configurationParameters) // .enableImplicitProviders(this.implicitConfigurationParametersEnabled); if (parentConfigurationParameters != null) { builder.parentConfigurationParameters(this.parentConfigurationParameters); } return builder.build(); } private LauncherDiscoveryListener getLauncherDiscoveryListener(ConfigurationParameters configurationParameters) { LauncherDiscoveryListener defaultDiscoveryListener = getDefaultLauncherDiscoveryListener( configurationParameters); if (discoveryListeners.isEmpty()) { return defaultDiscoveryListener; } if (discoveryListeners.contains(defaultDiscoveryListener)) { return LauncherDiscoveryListeners.composite(discoveryListeners); } List allDiscoveryListeners = new ArrayList<>(discoveryListeners.size() + 1); allDiscoveryListeners.addAll(discoveryListeners); allDiscoveryListeners.add(defaultDiscoveryListener); return LauncherDiscoveryListeners.composite(allDiscoveryListeners); } private LauncherDiscoveryListener getDefaultLauncherDiscoveryListener( ConfigurationParameters configurationParameters) { String value = configurationParameters.get(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME) // .orElse(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_VALUE); return LauncherDiscoveryListeners.fromConfigurationParameter( DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, value); } } LauncherDiscoveryResult.java000066400000000000000000000051451455764576500363530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableMap; import static java.util.stream.Collectors.toMap; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; /** * Represents the result of test discovery of the configured * {@linkplain TestEngine test engines}. * * @since 1.7 */ @API(status = INTERNAL, since = "1.7", consumers = { "org.junit.platform.testkit", "org.junit.platform.suite.engine" }) public class LauncherDiscoveryResult { private final Map testEngineDescriptors; private final ConfigurationParameters configurationParameters; LauncherDiscoveryResult(Map testEngineDescriptors, ConfigurationParameters configurationParameters) { this.testEngineDescriptors = unmodifiableMap(new LinkedHashMap<>(testEngineDescriptors)); this.configurationParameters = configurationParameters; } public TestDescriptor getEngineTestDescriptor(TestEngine testEngine) { return this.testEngineDescriptors.get(testEngine); } ConfigurationParameters getConfigurationParameters() { return configurationParameters; } public Collection getTestEngines() { return this.testEngineDescriptors.keySet(); } Collection getEngineTestDescriptors() { return this.testEngineDescriptors.values(); } public LauncherDiscoveryResult withRetainedEngines(Predicate predicate) { Map prunedTestEngineDescriptors = retainEngines(predicate); if (prunedTestEngineDescriptors.size() < testEngineDescriptors.size()) { return new LauncherDiscoveryResult(prunedTestEngineDescriptors, configurationParameters); } return this; } private Map retainEngines(Predicate predicate) { // @formatter:off return testEngineDescriptors.entrySet() .stream() .filter(entry -> predicate.test(entry.getValue())) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); // @formatter:on } } LauncherFactory.java000066400000000000000000000215671455764576500346220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.launcher.LauncherConstants.DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.TestExecutionListener; /** * Factory for creating {@link Launcher} instances by invoking {@link #create()} * or {@link #create(LauncherConfig)}. * *

By default, test engines are discovered at runtime using the * {@link java.util.ServiceLoader ServiceLoader} mechanism. For that purpose, a * text file named {@code META-INF/services/org.junit.platform.engine.TestEngine} * has to be added to the engine's JAR file in which the fully qualified name * of the implementation class of the {@link org.junit.platform.engine.TestEngine} * interface is declared. * *

By default, test execution listeners are discovered at runtime via the * {@link java.util.ServiceLoader ServiceLoader} mechanism and are * automatically registered with the {@link Launcher} created by this factory. * Users may register additional listeners using the * {@link Launcher#registerTestExecutionListeners(TestExecutionListener...)} * method on the created launcher instance. * *

For full control over automatic registration and programmatic registration * of test engines and listeners, supply an instance of {@link LauncherConfig} * to {@link #create(LauncherConfig)}. * * @since 1.0 * @see Launcher * @see LauncherConfig */ @API(status = STABLE, since = "1.0") public class LauncherFactory { private LauncherFactory() { /* no-op */ } /** * Factory method for opening a new {@link LauncherSession} using the * {@linkplain LauncherConfig#DEFAULT default} {@link LauncherConfig}. * * @throws PreconditionViolationException if no test engines are detected * @since 1.8 * @see #openSession(LauncherConfig) */ @API(status = STABLE, since = "1.10") public static LauncherSession openSession() throws PreconditionViolationException { return openSession(LauncherConfig.DEFAULT); } /** * Factory method for opening a new {@link LauncherSession} using the * supplied {@link LauncherConfig}. * * @param config the configuration for the session and the launcher; never * {@code null} * @throws PreconditionViolationException if the supplied configuration is * {@code null}, or if no test engines are detected * @since 1.8 * @see #openSession() */ @API(status = STABLE, since = "1.10") public static LauncherSession openSession(LauncherConfig config) throws PreconditionViolationException { Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); return new DefaultLauncherSession(collectLauncherInterceptors(configurationParameters), () -> createLauncherSessionListener(config), () -> createDefaultLauncher(config, configurationParameters)); } /** * Factory method for creating a new {@link Launcher} using the * {@linkplain LauncherConfig#DEFAULT default} {@link LauncherConfig}. * * @throws PreconditionViolationException if no test engines are detected * @see #create(LauncherConfig) */ public static Launcher create() throws PreconditionViolationException { return create(LauncherConfig.DEFAULT); } /** * Factory method for creating a new {@link Launcher} using the supplied * {@link LauncherConfig}. * * @param config the configuration for the launcher; never {@code null} * @throws PreconditionViolationException if the supplied configuration is * {@code null}, or if no test engines are detected * registered * @since 1.3 * @see #create() */ @API(status = STABLE, since = "1.10") public static Launcher create(LauncherConfig config) throws PreconditionViolationException { Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); return new SessionPerRequestLauncher(() -> createDefaultLauncher(config, configurationParameters), () -> createLauncherSessionListener(config), () -> collectLauncherInterceptors(configurationParameters)); } private static DefaultLauncher createDefaultLauncher(LauncherConfig config, LauncherConfigurationParameters configurationParameters) { Set engines = collectTestEngines(config); List filters = collectPostDiscoveryFilters(config); DefaultLauncher launcher = new DefaultLauncher(engines, filters); registerLauncherDiscoveryListeners(config, launcher); registerTestExecutionListeners(config, launcher, configurationParameters); return launcher; } private static List collectLauncherInterceptors( LauncherConfigurationParameters configurationParameters) { if (configurationParameters.getBoolean(ENABLE_LAUNCHER_INTERCEPTORS).orElse(false)) { List interceptors = new ArrayList<>(); ServiceLoaderRegistry.load(LauncherInterceptor.class).forEach(interceptors::add); return interceptors; } return emptyList(); } private static Set collectTestEngines(LauncherConfig config) { Set engines = new LinkedHashSet<>(); if (config.isTestEngineAutoRegistrationEnabled()) { new ServiceLoaderTestEngineRegistry().loadTestEngines().forEach(engines::add); } engines.addAll(config.getAdditionalTestEngines()); return engines; } private static LauncherSessionListener createLauncherSessionListener(LauncherConfig config) { ListenerRegistry listenerRegistry = ListenerRegistry.forLauncherSessionListeners(); if (config.isLauncherSessionListenerAutoRegistrationEnabled()) { ServiceLoaderRegistry.load(LauncherSessionListener.class).forEach(listenerRegistry::add); } config.getAdditionalLauncherSessionListeners().forEach(listenerRegistry::add); return listenerRegistry.getCompositeListener(); } private static List collectPostDiscoveryFilters(LauncherConfig config) { List filters = new ArrayList<>(); if (config.isPostDiscoveryFilterAutoRegistrationEnabled()) { ServiceLoaderRegistry.load(PostDiscoveryFilter.class).forEach(filters::add); } filters.addAll(config.getAdditionalPostDiscoveryFilters()); return filters; } private static void registerLauncherDiscoveryListeners(LauncherConfig config, Launcher launcher) { if (config.isLauncherDiscoveryListenerAutoRegistrationEnabled()) { ServiceLoaderRegistry.load(LauncherDiscoveryListener.class).forEach( launcher::registerLauncherDiscoveryListeners); } config.getAdditionalLauncherDiscoveryListeners().forEach(launcher::registerLauncherDiscoveryListeners); } private static void registerTestExecutionListeners(LauncherConfig config, Launcher launcher, LauncherConfigurationParameters configurationParameters) { if (config.isTestExecutionListenerAutoRegistrationEnabled()) { loadAndFilterTestExecutionListeners(configurationParameters).forEach( launcher::registerTestExecutionListeners); } config.getAdditionalTestExecutionListeners().forEach(launcher::registerTestExecutionListeners); } private static Stream loadAndFilterTestExecutionListeners( ConfigurationParameters configurationParameters) { Iterable listeners = ServiceLoaderRegistry.load(TestExecutionListener.class); String deactivatedListenersPattern = configurationParameters.get( DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME).orElse(null); // @formatter:off return StreamSupport.stream(listeners.spliterator(), false) .filter(ClassNamePatternFilterUtils.excludeMatchingClasses(deactivatedListenersPattern)); // @formatter:on } } LauncherListenerRegistry.java000066400000000000000000000013721455764576500365210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.TestExecutionListener; class LauncherListenerRegistry { final ListenerRegistry launcherDiscoveryListeners = ListenerRegistry.forLauncherDiscoveryListeners(); final ListenerRegistry testExecutionListeners = ListenerRegistry.forTestExecutionListeners(); } ListenerRegistry.java000066400000000000000000000061011455764576500350320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.function.Function; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners; import org.junit.platform.launcher.listeners.session.LauncherSessionListeners; class ListenerRegistry { private final Function, T> compositeListenerFactory; static ListenerRegistry forLauncherSessionListeners() { return create(LauncherSessionListeners::composite); } static ListenerRegistry forLauncherDiscoveryListeners() { return create(LauncherDiscoveryListeners::composite); } static ListenerRegistry forTestExecutionListeners() { return create(CompositeTestExecutionListener::new); } static ListenerRegistry forEngineExecutionListeners() { return create(CompositeEngineExecutionListener::new); } static ListenerRegistry create(Function, T> compositeListenerFactory) { return new ListenerRegistry<>(compositeListenerFactory); } static ListenerRegistry copyOf(ListenerRegistry source) { ListenerRegistry registry = new ListenerRegistry<>(source.compositeListenerFactory); if (!source.listeners.isEmpty()) { registry.addAll(source.listeners); } return registry; } private final ArrayList listeners = new ArrayList<>(); private ListenerRegistry(Function, T> compositeListenerFactory) { this.compositeListenerFactory = compositeListenerFactory; } ListenerRegistry add(T listener) { Preconditions.notNull(listener, "listener must not be null"); this.listeners.add(listener); return this; } @SafeVarargs @SuppressWarnings("varargs") final ListenerRegistry addAll(T... listeners) { Preconditions.notEmpty(listeners, "listeners array must not be null or empty"); return addAll(Arrays.asList(listeners)); } ListenerRegistry addAll(Collection listeners) { Preconditions.notEmpty(listeners, "listeners collection must not be null or empty"); Preconditions.containsNoNullElements(listeners, "individual listeners must not be null"); this.listeners.addAll(listeners); return this; } T getCompositeListener() { this.listeners.trimToSize(); return compositeListenerFactory.apply(this.listeners); } List getListeners() { return Collections.unmodifiableList(this.listeners); } } OutcomeDelayingEngineExecutionListener.java000066400000000000000000000050061455764576500413270ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; /** * Delays reporting of engine skipped/finished events so that exceptions thrown * by engines can be reported to listeners. * * @since 1.6 */ class OutcomeDelayingEngineExecutionListener extends DelegatingEngineExecutionListener { private final TestDescriptor engineDescriptor; private volatile boolean engineStarted; private volatile Outcome outcome; private volatile String skipReason; private volatile TestExecutionResult executionResult; OutcomeDelayingEngineExecutionListener(EngineExecutionListener delegate, TestDescriptor engineDescriptor) { super(delegate); this.engineDescriptor = engineDescriptor; } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { if (testDescriptor == engineDescriptor) { outcome = Outcome.SKIPPED; skipReason = reason; } else { super.executionSkipped(testDescriptor, reason); } } @Override public void executionStarted(TestDescriptor testDescriptor) { if (testDescriptor == engineDescriptor) { engineStarted = true; } super.executionStarted(testDescriptor); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult executionResult) { if (testDescriptor == engineDescriptor) { outcome = Outcome.FINISHED; this.executionResult = executionResult; } else { super.executionFinished(testDescriptor, executionResult); } } void reportEngineOutcome() { if (outcome == Outcome.FINISHED) { super.executionFinished(engineDescriptor, executionResult); } else if (outcome == Outcome.SKIPPED) { super.executionSkipped(engineDescriptor, skipReason); } } void reportEngineFailure(Throwable throwable) { if (!engineStarted) { super.executionStarted(engineDescriptor); } if (executionResult != null && executionResult.getThrowable().isPresent()) { throwable.addSuppressed(executionResult.getThrowable().get()); } super.executionFinished(engineDescriptor, TestExecutionResult.failed(throwable)); } private enum Outcome { SKIPPED, FINISHED } } ServiceLoaderRegistry.java000066400000000000000000000023651455764576500360040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import java.util.ServiceLoader; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; /** * @since 1.8 */ class ServiceLoaderRegistry { static Iterable load(Class serviceProviderClass) { Iterable listeners = ServiceLoader.load(serviceProviderClass, ClassLoaderUtils.getDefaultClassLoader()); getLogger().config(() -> "Loaded " + serviceProviderClass.getSimpleName() + " instances: " + stream(listeners.spliterator(), false).map(Object::toString).collect(toList())); return listeners; } private static Logger getLogger() { // Not a constant to avoid problems with building GraalVM native images return LoggerFactory.getLogger(ServiceLoaderRegistry.class); } } ServiceLoaderTestEngineRegistry.java000066400000000000000000000025431455764576500377700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ServiceLoader; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.engine.TestEngine; /** * @since 1.0 */ @API(status = INTERNAL, since = "1.0", consumers = "org.junit.platform.suite.engine") public final class ServiceLoaderTestEngineRegistry { public ServiceLoaderTestEngineRegistry() { } public Iterable loadTestEngines() { Iterable testEngines = ServiceLoader.load(TestEngine.class, ClassLoaderUtils.getDefaultClassLoader()); getLogger().config(() -> TestEngineFormatter.format("Discovered TestEngines", testEngines)); return testEngines; } private static Logger getLogger() { // Not a constant to avoid problems with building GraalVM native images return LoggerFactory.getLogger(ServiceLoaderTestEngineRegistry.class); } } SessionPerRequestLauncher.java000066400000000000000000000057321455764576500366520ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.List; import java.util.function.Supplier; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * @since 1.8 */ class SessionPerRequestLauncher implements Launcher { private final LauncherListenerRegistry listenerRegistry = new LauncherListenerRegistry(); private final Supplier launcherSupplier; private final Supplier sessionListenerSupplier; private final Supplier> interceptorFactory; SessionPerRequestLauncher(Supplier launcherSupplier, Supplier sessionListenerSupplier, Supplier> interceptorFactory) { this.launcherSupplier = launcherSupplier; this.sessionListenerSupplier = sessionListenerSupplier; this.interceptorFactory = interceptorFactory; } @Override public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { listenerRegistry.launcherDiscoveryListeners.addAll(listeners); } @Override public void registerTestExecutionListeners(TestExecutionListener... listeners) { listenerRegistry.testExecutionListeners.addAll(listeners); } @Override public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { try (LauncherSession session = createSession()) { return session.getLauncher().discover(launcherDiscoveryRequest); } } @Override public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { try (LauncherSession session = createSession()) { session.getLauncher().execute(launcherDiscoveryRequest, listeners); } } @Override public void execute(TestPlan testPlan, TestExecutionListener... listeners) { try (LauncherSession session = createSession()) { session.getLauncher().execute(testPlan, listeners); } } private LauncherSession createSession() { LauncherSession session = new DefaultLauncherSession(interceptorFactory.get(), sessionListenerSupplier, launcherSupplier); Launcher launcher = session.getLauncher(); listenerRegistry.launcherDiscoveryListeners.getListeners().forEach( launcher::registerLauncherDiscoveryListeners); listenerRegistry.testExecutionListeners.getListeners().forEach(launcher::registerTestExecutionListeners); return session; } } StackTracePruningEngineExecutionListener.java000066400000000000000000000043371455764576500416340ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; /** * Prunes the stack trace in case of a failed event. * * @since 1.10 * @see org.junit.platform.commons.util.ExceptionUtils#pruneStackTrace(Throwable, List) */ class StackTracePruningEngineExecutionListener extends DelegatingEngineExecutionListener { StackTracePruningEngineExecutionListener(EngineExecutionListener delegate) { super(delegate); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { List testClassNames = getTestClassNames(testDescriptor); if (testExecutionResult.getThrowable().isPresent()) { Throwable throwable = testExecutionResult.getThrowable().get(); ExceptionUtils.findNestedThrowables(throwable).forEach( t -> ExceptionUtils.pruneStackTrace(t, testClassNames)); } super.executionFinished(testDescriptor, testExecutionResult); } private static List getTestClassNames(TestDescriptor testDescriptor) { return testDescriptor.getAncestors() // .stream() // .map(TestDescriptor::getSource) // .filter(Optional::isPresent) // .map(Optional::get) // .map(source -> { if (source instanceof ClassSource) { return ((ClassSource) source).getClassName(); } else if (source instanceof MethodSource) { return ((MethodSource) source).getClassName(); } else { return null; } }) // .filter(Objects::nonNull) // .collect(Collectors.toList()); } } StreamInterceptingTestExecutionListener.java000066400000000000000000000101171455764576500415570ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_MAX_BUFFER_DEFAULT; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_MAX_BUFFER_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.LauncherConstants.STDOUT_REPORT_ENTRY_KEY; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.function.BiConsumer; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.core.CompositeTestExecutionListener.EagerTestExecutionListener; /** * @since 1.3 */ class StreamInterceptingTestExecutionListener implements EagerTestExecutionListener { private final Optional stdoutInterceptor; private final Optional stderrInterceptor; private final BiConsumer reporter; static Optional create(ConfigurationParameters configurationParameters, BiConsumer reporter) { boolean captureStdout = configurationParameters.getBoolean(CAPTURE_STDOUT_PROPERTY_NAME).orElse(false); boolean captureStderr = configurationParameters.getBoolean(CAPTURE_STDERR_PROPERTY_NAME).orElse(false); if (!captureStdout && !captureStderr) { return Optional.empty(); } int maxSize = configurationParameters.get(CAPTURE_MAX_BUFFER_PROPERTY_NAME, Integer::valueOf) // .orElse(CAPTURE_MAX_BUFFER_DEFAULT); Optional stdoutInterceptor = captureStdout ? StreamInterceptor.registerStdout(maxSize) : Optional.empty(); Optional stderrInterceptor = captureStderr ? StreamInterceptor.registerStderr(maxSize) : Optional.empty(); if ((!stdoutInterceptor.isPresent() && captureStdout) || (!stderrInterceptor.isPresent() && captureStderr)) { stdoutInterceptor.ifPresent(StreamInterceptor::unregister); stderrInterceptor.ifPresent(StreamInterceptor::unregister); return Optional.empty(); } return Optional.of(new StreamInterceptingTestExecutionListener(stdoutInterceptor, stderrInterceptor, reporter)); } private StreamInterceptingTestExecutionListener(Optional stdoutInterceptor, Optional stderrInterceptor, BiConsumer reporter) { this.stdoutInterceptor = stdoutInterceptor; this.stderrInterceptor = stderrInterceptor; this.reporter = reporter; } void unregister() { stdoutInterceptor.ifPresent(StreamInterceptor::unregister); stderrInterceptor.ifPresent(StreamInterceptor::unregister); } @Override public void executionJustStarted(TestIdentifier testIdentifier) { stdoutInterceptor.ifPresent(StreamInterceptor::capture); stderrInterceptor.ifPresent(StreamInterceptor::capture); } @Override public void executionJustFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { Map map = new HashMap<>(); String out = stdoutInterceptor.map(StreamInterceptor::consume).orElse(""); if (StringUtils.isNotBlank(out)) { map.put(STDOUT_REPORT_ENTRY_KEY, out); } String err = stderrInterceptor.map(StreamInterceptor::consume).orElse(""); if (StringUtils.isNotBlank(err)) { map.put(STDERR_REPORT_ENTRY_KEY, err); } if (!map.isEmpty()) { reporter.accept(testIdentifier, ReportEntry.from(map)); } } } StreamInterceptor.java000066400000000000000000000062501455764576500351730ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayDeque; import java.util.Deque; import java.util.Optional; import java.util.function.Consumer; /** * @since 1.3 */ class StreamInterceptor extends PrintStream { private final PrintStream originalStream; private final Consumer unregisterAction; private final int maxNumberOfBytesPerThread; private final ThreadLocal output = ThreadLocal.withInitial( RewindableByteArrayOutputStream::new); static Optional registerStdout(int maxNumberOfBytesPerThread) { return register(System.out, System::setOut, maxNumberOfBytesPerThread); } static Optional registerStderr(int maxNumberOfBytesPerThread) { return register(System.err, System::setErr, maxNumberOfBytesPerThread); } static Optional register(PrintStream originalStream, Consumer streamSetter, int maxNumberOfBytesPerThread) { if (originalStream instanceof StreamInterceptor) { return Optional.empty(); } StreamInterceptor interceptor = new StreamInterceptor(originalStream, streamSetter, maxNumberOfBytesPerThread); streamSetter.accept(interceptor); return Optional.of(interceptor); } private StreamInterceptor(PrintStream originalStream, Consumer unregisterAction, int maxNumberOfBytesPerThread) { super(originalStream); this.originalStream = originalStream; this.unregisterAction = unregisterAction; this.maxNumberOfBytesPerThread = maxNumberOfBytesPerThread; } void capture() { output.get().mark(); } String consume() { return output.get().rewind(); } void unregister() { unregisterAction.accept(originalStream); } @Override public void write(int b) { RewindableByteArrayOutputStream out = output.get(); if (out.isMarked() && out.size() < maxNumberOfBytesPerThread) { out.write(b); } super.write(b); } @Override public void write(byte[] b) { write(b, 0, b.length); } @Override public void write(byte[] buf, int off, int len) { RewindableByteArrayOutputStream out = output.get(); if (out.isMarked()) { int actualLength = Math.max(0, Math.min(len, maxNumberOfBytesPerThread - out.size())); if (actualLength > 0) { out.write(buf, off, actualLength); } } super.write(buf, off, len); } static class RewindableByteArrayOutputStream extends ByteArrayOutputStream { private final Deque markedPositions = new ArrayDeque<>(); boolean isMarked() { return !markedPositions.isEmpty(); } void mark() { markedPositions.addFirst(count); } String rewind() { Integer position = markedPositions.pollFirst(); if (position == null || position == count) { return ""; } int length = count - position; count -= length; return new String(buf, position, length); } } } TestEngineFormatter.java000066400000000000000000000033631455764576500354540ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.lang.String.join; import static java.util.stream.Collectors.joining; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; import org.junit.platform.commons.util.ClassLoaderUtils; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.engine.TestEngine; class TestEngineFormatter { private TestEngineFormatter() { } @SuppressWarnings("unchecked") static String format(String title, Iterable testEngines) { return format(title, (Stream) CollectionUtils.toStream(testEngines)); } private static String format(String title, Stream testEngines) { String details = testEngines // .map(engine -> String.format("- %s (%s)", engine.getId(), join(", ", computeAttributes(engine)))) // .collect(joining("\n")); return title + ":" + (details.isEmpty() ? " " : "\n" + details); } private static List computeAttributes(TestEngine engine) { List attributes = new ArrayList<>(4); engine.getGroupId().ifPresent(groupId -> attributes.add("group ID: " + groupId)); engine.getArtifactId().ifPresent(artifactId -> attributes.add("artifact ID: " + artifactId)); engine.getVersion().ifPresent(version -> attributes.add("version: " + version)); ClassLoaderUtils.getLocation(engine).ifPresent(location -> attributes.add("location: " + location)); return attributes; } } package-info.java000066400000000000000000000005331455764576500340430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/** * Core support classes for the {@link org.junit.platform.launcher.Launcher Launcher} * including the {@link org.junit.platform.launcher.core.LauncherFactory LauncherFactory} * and the {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder * LauncherDiscoveryRequestBuilder}. */ package org.junit.platform.launcher.core; junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/000077500000000000000000000000001455764576500320125ustar00rootroot00000000000000LegacyReportingUtils.java000066400000000000000000000057631455764576500367300ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Utility methods for dealing with legacy reporting infrastructure, such as * reporting systems built on the Ant-based XML reporting format for JUnit 4. * * @since 1.0.3 * @deprecated Use {@link org.junit.platform.reporting.legacy.LegacyReportingUtils} * instead. */ @Deprecated @SuppressWarnings("JavadocReference") @API(status = DEPRECATED, since = "1.6") public class LegacyReportingUtils { private LegacyReportingUtils() { /* no-op */ } /** * Get the class name for the supplied {@link TestIdentifier} using the * supplied {@link TestPlan}. * *

This implementation attempts to find the closest test identifier with * a {@link ClassSource} by traversing the hierarchy upwards towards the * root starting with the supplied test identifier. In case no such source * is found, it falls back to using the parent's * {@linkplain TestIdentifier#getLegacyReportingName legacy reporting name}. * * @param testPlan the test plan that contains the {@code TestIdentifier}; * never {@code null} * @param testIdentifier the identifier to determine the class name for; * never {@code null} * @see TestIdentifier#getLegacyReportingName */ public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifier) { Preconditions.notNull(testPlan, "testPlan must not be null"); Preconditions.notNull(testIdentifier, "testIdentifier must not be null"); for (TestIdentifier current = testIdentifier; current != null; current = getParent(testPlan, current)) { ClassSource source = getClassSource(current); if (source != null) { return source.getClassName(); } } return getParentLegacyReportingName(testPlan, testIdentifier); } private static TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { return testPlan.getParent(testIdentifier).orElse(null); } private static ClassSource getClassSource(TestIdentifier current) { // @formatter:off return current.getSource() .filter(ClassSource.class::isInstance) .map(ClassSource.class::cast) .orElse(null); // @formatter:on } private static String getParentLegacyReportingName(TestPlan testPlan, TestIdentifier testIdentifier) { // @formatter:off return testPlan.getParent(testIdentifier) .map(TestIdentifier::getLegacyReportingName) .orElse(""); // @formatter:on } } LoggingListener.java000066400000000000000000000104741455764576500357000ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Simple {@link TestExecutionListener} for logging informational messages * for all events via a {@link BiConsumer} that consumes {@code Throwable} * and {@code Supplier}. * * @since 1.0 * @see #forJavaUtilLogging() * @see #forJavaUtilLogging(Level) * @see LoggingListener#LoggingListener(BiConsumer) */ @API(status = MAINTAINED, since = "1.0") public class LoggingListener implements TestExecutionListener { /** * Create a {@code LoggingListener} which delegates to a * {@link java.util.logging.Logger} using a log level of * {@link Level#FINE FINE}. * * @see #forJavaUtilLogging(Level) * @see #forBiConsumer(BiConsumer) */ public static LoggingListener forJavaUtilLogging() { return forJavaUtilLogging(Level.FINE); } /** * Create a {@code LoggingListener} which delegates to a * {@link java.util.logging.Logger} using the supplied * {@linkplain Level log level}. * * @param logLevel the log level to use; never {@code null} * @see #forJavaUtilLogging() * @see #forBiConsumer(BiConsumer) */ public static LoggingListener forJavaUtilLogging(Level logLevel) { Preconditions.notNull(logLevel, "logLevel must not be null"); Logger logger = Logger.getLogger(LoggingListener.class.getName()); return new LoggingListener((t, messageSupplier) -> logger.log(logLevel, t, messageSupplier)); } /** * Create a {@code LoggingListener} which delegates to the supplied * {@link BiConsumer} for consumption of logging messages. * *

The {@code BiConsumer's} arguments are a {@link Throwable} (potentially * {@code null}) and a {@link Supplier} (never {@code null}) for the log * message. * * @param logger a logger implemented as a {@code BiConsumer}; * never {@code null} * * @see #forJavaUtilLogging() * @see #forJavaUtilLogging(Level) */ public static LoggingListener forBiConsumer(BiConsumer> logger) { return new LoggingListener(logger); } private final BiConsumer> logger; private LoggingListener(BiConsumer> logger) { this.logger = Preconditions.notNull(logger, "logger must not be null"); } @Override public void testPlanExecutionStarted(TestPlan testPlan) { log("TestPlan Execution Started: %s", testPlan); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { log("TestPlan Execution Finished: %s", testPlan); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { log("Dynamic Test Registered: %s - %s", testIdentifier.getDisplayName(), testIdentifier.getUniqueId()); } @Override public void executionStarted(TestIdentifier testIdentifier) { log("Execution Started: %s - %s", testIdentifier.getDisplayName(), testIdentifier.getUniqueId()); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { log("Execution Skipped: %s - %s - %s", testIdentifier.getDisplayName(), testIdentifier.getUniqueId(), reason); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { logWithThrowable("Execution Finished: %s - %s - %s", testExecutionResult.getThrowable().orElse(null), testIdentifier.getDisplayName(), testIdentifier.getUniqueId(), testExecutionResult); } private void log(String message, Object... args) { logWithThrowable(message, null, args); } private void logWithThrowable(String message, Throwable t, Object... args) { this.logger.accept(t, () -> String.format(message, args)); } } MutableTestExecutionSummary.java000066400000000000000000000220411455764576500402700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static java.lang.String.join; import static java.util.Collections.synchronizedList; import java.io.PrintWriter; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Mutable, internal implementation of the {@link TestExecutionSummary} API. * * @since 1.0 */ class MutableTestExecutionSummary implements TestExecutionSummary { private static final String TAB = " "; private static final String DOUBLE_TAB = TAB + TAB; private static final int DEFAULT_MAX_STACKTRACE_LINES = 10; private static final String CAUSED_BY = "Caused by: "; private static final String SUPPRESSED = "Suppressed: "; private static final String CIRCULAR = "Circular reference: "; final AtomicLong containersFound = new AtomicLong(); final AtomicLong containersStarted = new AtomicLong(); final AtomicLong containersSkipped = new AtomicLong(); final AtomicLong containersAborted = new AtomicLong(); final AtomicLong containersSucceeded = new AtomicLong(); final AtomicLong containersFailed = new AtomicLong(); final AtomicLong testsFound = new AtomicLong(); final AtomicLong testsStarted = new AtomicLong(); final AtomicLong testsSkipped = new AtomicLong(); final AtomicLong testsAborted = new AtomicLong(); final AtomicLong testsSucceeded = new AtomicLong(); final AtomicLong testsFailed = new AtomicLong(); private final TestPlan testPlan; private final List failures = synchronizedList(new ArrayList<>()); private final long timeStarted; private final long timeStartedNanos; long timeFinished; long timeFinishedNanos; MutableTestExecutionSummary(TestPlan testPlan) { this.testPlan = testPlan; this.containersFound.set(testPlan.countTestIdentifiers(TestIdentifier::isContainer)); this.testsFound.set(testPlan.countTestIdentifiers(TestIdentifier::isTest)); this.timeStarted = System.currentTimeMillis(); this.timeStartedNanos = System.nanoTime(); } void addFailure(TestIdentifier testIdentifier, Throwable throwable) { this.failures.add(new DefaultFailure(testIdentifier, throwable)); } @Override public long getTimeStarted() { return this.timeStarted; } @Override public long getTimeFinished() { return this.timeFinished; } @Override public long getTotalFailureCount() { return getTestsFailedCount() + getContainersFailedCount(); } @Override public long getContainersFoundCount() { return this.containersFound.get(); } @Override public long getContainersStartedCount() { return this.containersStarted.get(); } @Override public long getContainersSkippedCount() { return this.containersSkipped.get(); } @Override public long getContainersAbortedCount() { return this.containersAborted.get(); } @Override public long getContainersSucceededCount() { return this.containersSucceeded.get(); } @Override public long getContainersFailedCount() { return this.containersFailed.get(); } @Override public long getTestsFoundCount() { return this.testsFound.get(); } @Override public long getTestsStartedCount() { return this.testsStarted.get(); } @Override public long getTestsSkippedCount() { return this.testsSkipped.get(); } @Override public long getTestsAbortedCount() { return this.testsAborted.get(); } @Override public long getTestsSucceededCount() { return this.testsSucceeded.get(); } @Override public long getTestsFailedCount() { return this.testsFailed.get(); } @Override public void printTo(PrintWriter writer) { // @formatter:off writer.printf("%nTest run finished after %d ms%n" + "[%10d containers found ]%n" + "[%10d containers skipped ]%n" + "[%10d containers started ]%n" + "[%10d containers aborted ]%n" + "[%10d containers successful ]%n" + "[%10d containers failed ]%n" + "[%10d tests found ]%n" + "[%10d tests skipped ]%n" + "[%10d tests started ]%n" + "[%10d tests aborted ]%n" + "[%10d tests successful ]%n" + "[%10d tests failed ]%n" + "%n", Duration.ofNanos(this.timeFinishedNanos - this.timeStartedNanos).toMillis(), getContainersFoundCount(), getContainersSkippedCount(), getContainersStartedCount(), getContainersAbortedCount(), getContainersSucceededCount(), getContainersFailedCount(), getTestsFoundCount(), getTestsSkippedCount(), getTestsStartedCount(), getTestsAbortedCount(), getTestsSucceededCount(), getTestsFailedCount() ); // @formatter:on writer.flush(); } @Override public void printFailuresTo(PrintWriter writer) { printFailuresTo(writer, DEFAULT_MAX_STACKTRACE_LINES); } @Override public void printFailuresTo(PrintWriter writer, int maxStackTraceLines) { Preconditions.notNull(writer, "PrintWriter must not be null"); Preconditions.condition(maxStackTraceLines >= 0, "maxStackTraceLines must be a positive number"); if (getTotalFailureCount() > 0) { writer.printf("%nFailures (%d):%n", getTotalFailureCount()); this.failures.forEach(failure -> { writer.printf("%s%s%n", TAB, describeTest(failure.getTestIdentifier())); printSource(writer, failure.getTestIdentifier()); writer.printf("%s=> %s%n", DOUBLE_TAB, failure.getException()); printStackTrace(writer, failure.getException(), maxStackTraceLines); }); writer.flush(); } } @Override public List getFailures() { return Collections.unmodifiableList(failures); } private String describeTest(TestIdentifier testIdentifier) { List descriptionParts = new ArrayList<>(); collectTestDescription(testIdentifier, descriptionParts); return join(":", descriptionParts); } private void collectTestDescription(TestIdentifier identifier, List descriptionParts) { descriptionParts.add(0, identifier.getDisplayName()); this.testPlan.getParent(identifier).ifPresent(parent -> collectTestDescription(parent, descriptionParts)); } private void printSource(PrintWriter writer, TestIdentifier testIdentifier) { testIdentifier.getSource().ifPresent(source -> writer.printf("%s%s%n", DOUBLE_TAB, source)); } private void printStackTrace(PrintWriter writer, Throwable throwable, int max) { if (throwable.getCause() != null || (throwable.getSuppressed() != null && throwable.getSuppressed().length > 0)) { max = max / 2; } printStackTrace(writer, new StackTraceElement[] {}, throwable, "", DOUBLE_TAB + " ", new HashSet<>(), max); writer.flush(); } private void printStackTrace(PrintWriter writer, StackTraceElement[] parentTrace, Throwable throwable, String caption, String indentation, Set seenThrowables, int max) { if (seenThrowables.contains(throwable)) { writer.printf("%s%s[%s%s]%n", indentation, TAB, CIRCULAR, throwable); return; } seenThrowables.add(throwable); StackTraceElement[] trace = throwable.getStackTrace(); if (parentTrace != null && parentTrace.length > 0) { writer.printf("%s%s%s%n", indentation, caption, throwable); } int duplicates = numberOfCommonFrames(trace, parentTrace); int numDistinctFrames = trace.length - duplicates; int numDisplayLines = Math.min(numDistinctFrames, max); for (int i = 0; i < numDisplayLines; i++) { writer.printf("%s%s%s%n", indentation, TAB, trace[i]); } if (trace.length > max || duplicates != 0) { writer.printf("%s%s%s%n", indentation, TAB, "[...]"); } for (Throwable suppressed : throwable.getSuppressed()) { printStackTrace(writer, trace, suppressed, SUPPRESSED, indentation + TAB, seenThrowables, max); } if (throwable.getCause() != null) { printStackTrace(writer, trace, throwable.getCause(), CAUSED_BY, indentation, seenThrowables, max); } } private int numberOfCommonFrames(StackTraceElement[] currentTrace, StackTraceElement[] parentTrace) { int currentIndex = currentTrace.length - 1; for (int parentIndex = parentTrace.length - 1; currentIndex >= 0 && parentIndex >= 0; currentIndex--, parentIndex--) { if (!currentTrace[currentIndex].equals(parentTrace[parentIndex])) { break; } } return currentTrace.length - 1 - currentIndex; } private static class DefaultFailure implements Failure { private static final long serialVersionUID = 1L; private final TestIdentifier testIdentifier; private final Throwable exception; DefaultFailure(TestIdentifier testIdentifier, Throwable exception) { this.testIdentifier = testIdentifier; this.exception = exception; } @Override public TestIdentifier getTestIdentifier() { return testIdentifier; } @Override public Throwable getException() { return exception; } } } OutputDir.java000066400000000000000000000055471455764576500345500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.SecureRandom; import java.util.Optional; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.util.StringUtils; @API(status = INTERNAL, since = "1.9") public class OutputDir { public static OutputDir create(Optional customDir) { try { return createSafely(customDir, () -> Paths.get(".").toAbsolutePath()); } catch (IOException e) { throw new UncheckedIOException("Failed to create output dir", e); } } /** * Package private for testing purposes. */ static OutputDir createSafely(Optional customDir, Supplier currentWorkingDir) throws IOException { Path cwd = currentWorkingDir.get(); Path outputDir; if (customDir.isPresent() && StringUtils.isNotBlank(customDir.get())) { outputDir = cwd.resolve(customDir.get()); } else if (Files.exists(cwd.resolve("pom.xml"))) { outputDir = cwd.resolve("target"); } else if (containsFilesWithExtensions(cwd, ".gradle", ".gradle.kts")) { outputDir = cwd.resolve("build"); } else { outputDir = cwd; } if (!Files.exists(outputDir)) { Files.createDirectories(outputDir); } return new OutputDir(outputDir); } private final Path path; private OutputDir(Path path) { this.path = path; } public Path toPath() { return path; } public Path createFile(String prefix, String extension) throws UncheckedIOException { String filename = String.format("%s-%d.%s", prefix, Math.abs(new SecureRandom().nextLong()), extension); Path outputFile = path.resolve(filename); try { if (Files.exists(outputFile)) { Files.delete(outputFile); } return Files.createFile(outputFile); } catch (IOException e) { throw new UncheckedIOException("Failed to create output file: " + outputFile, e); } } /** * Determine if the supplied directory contains files with any of the * supplied extensions. */ private static boolean containsFilesWithExtensions(Path dir, String... extensions) throws IOException { return Files.find(dir, 1, // (path, basicFileAttributes) -> { if (basicFileAttributes.isRegularFile()) { for (String extension : extensions) { if (path.getFileName().toString().endsWith(extension)) { return true; } } } return false; }) // .findFirst() // .isPresent(); } } SummaryGeneratingListener.java000066400000000000000000000074631455764576500377570ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static java.util.stream.Stream.concat; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Simple {@link TestExecutionListener} that generates a * {@linkplain TestExecutionSummary summary} of the test execution. * * @since 1.0 * @see #getSummary() */ @API(status = MAINTAINED, since = "1.0") public class SummaryGeneratingListener implements TestExecutionListener { private TestPlan testPlan; private MutableTestExecutionSummary summary; public SummaryGeneratingListener() { } /** * Get the summary generated by this listener. */ public TestExecutionSummary getSummary() { return this.summary; } @Override public void testPlanExecutionStarted(TestPlan testPlan) { this.testPlan = testPlan; this.summary = new MutableTestExecutionSummary(testPlan); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { this.summary.timeFinished = System.currentTimeMillis(); this.summary.timeFinishedNanos = System.nanoTime(); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { if (testIdentifier.isContainer()) { this.summary.containersFound.incrementAndGet(); } if (testIdentifier.isTest()) { this.summary.testsFound.incrementAndGet(); } } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { // @formatter:off long skippedContainers = concat(Stream.of(testIdentifier), testPlan.getDescendants(testIdentifier).stream()) .filter(TestIdentifier::isContainer) .count(); long skippedTests = concat(Stream.of(testIdentifier), testPlan.getDescendants(testIdentifier).stream()) .filter(TestIdentifier::isTest) .count(); // @formatter:on this.summary.containersSkipped.addAndGet(skippedContainers); this.summary.testsSkipped.addAndGet(skippedTests); } @Override public void executionStarted(TestIdentifier testIdentifier) { if (testIdentifier.isContainer()) { this.summary.containersStarted.incrementAndGet(); } if (testIdentifier.isTest()) { this.summary.testsStarted.incrementAndGet(); } } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { switch (testExecutionResult.getStatus()) { case SUCCESSFUL: { if (testIdentifier.isContainer()) { this.summary.containersSucceeded.incrementAndGet(); } if (testIdentifier.isTest()) { this.summary.testsSucceeded.incrementAndGet(); } break; } case ABORTED: { if (testIdentifier.isContainer()) { this.summary.containersAborted.incrementAndGet(); } if (testIdentifier.isTest()) { this.summary.testsAborted.incrementAndGet(); } break; } case FAILED: { if (testIdentifier.isContainer()) { this.summary.containersFailed.incrementAndGet(); } if (testIdentifier.isTest()) { this.summary.testsFailed.incrementAndGet(); } testExecutionResult.getThrowable().ifPresent( throwable -> this.summary.addFailure(testIdentifier, throwable)); break; } default: throw new PreconditionViolationException( "Unsupported execution status:" + testExecutionResult.getStatus()); } } } TestExecutionSummary.java000066400000000000000000000106461455764576500367660ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.PrintWriter; import java.io.Serializable; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.launcher.TestIdentifier; /** * Summary of test plan execution. * * @since 1.0 * @see SummaryGeneratingListener */ @API(status = MAINTAINED, since = "1.0") public interface TestExecutionSummary { /** * Get the timestamp (in milliseconds) when the test plan started. */ long getTimeStarted(); /** * Get the timestamp (in milliseconds) when the test plan finished. */ long getTimeFinished(); /** * Get the total number of {@linkplain #getContainersFailedCount failed * containers} and {@linkplain #getTestsFailedCount failed tests}. * * @see #getTestsFailedCount() * @see #getContainersFailedCount() */ long getTotalFailureCount(); /** * Get the number of containers found. */ long getContainersFoundCount(); /** * Get the number of containers started. */ long getContainersStartedCount(); /** * Get the number of containers skipped. */ long getContainersSkippedCount(); /** * Get the number of containers aborted. */ long getContainersAbortedCount(); /** * Get the number of containers that succeeded. */ long getContainersSucceededCount(); /** * Get the number of containers that failed. * * @see #getTestsFailedCount() * @see #getTotalFailureCount() */ long getContainersFailedCount(); /** * Get the number of tests found. */ long getTestsFoundCount(); /** * Get the number of tests started. */ long getTestsStartedCount(); /** * Get the number of tests skipped. */ long getTestsSkippedCount(); /** * Get the number of tests aborted. */ long getTestsAbortedCount(); /** * Get the number of tests that succeeded. */ long getTestsSucceededCount(); /** * Get the number of tests that failed. * * @see #getContainersFailedCount() * @see #getTotalFailureCount() */ long getTestsFailedCount(); /** * Print this summary to the supplied {@link PrintWriter}. * *

This method does not print failure messages. * * @see #printFailuresTo(PrintWriter) */ void printTo(PrintWriter writer); /** * Print failed containers and tests, including sources and exception * messages, to the supplied {@link PrintWriter}. * * @param writer the {@code PrintWriter} to which to print; never {@code null} * @see #printTo(PrintWriter) * @see #printFailuresTo(PrintWriter, int) */ void printFailuresTo(PrintWriter writer); /** * Print failed containers and tests, including sources and exception * messages, to the supplied {@link PrintWriter}. * *

The maximum number of lines to print for exception stack traces (if any) * can be specified via the {@code maxStackTraceLines} argument. * *

By default, this method delegates to {@link #printFailuresTo(PrintWriter)}, * effectively ignoring the {@code maxStackTraceLines} argument. Concrete * implementations of this interface should therefore override this default * method in order to honor the {@code maxStackTraceLines} argument. * * @param writer the {@code PrintWriter} to which to print; never {@code null} * @param maxStackTraceLines the maximum number of lines to print for exception * stack traces; must be a positive value * @since 1.6 * @see #printTo(PrintWriter) * @see #printFailuresTo(PrintWriter) */ @API(status = MAINTAINED, since = "1.6") default void printFailuresTo(PrintWriter writer, int maxStackTraceLines) { printFailuresTo(writer); } /** * Get an immutable list of the failures of the test plan execution. */ List getFailures(); /** * Failure of a test or container. */ interface Failure extends Serializable { /** * Get the identifier of the failed test or container. * * @return the {@link TestIdentifier} for this failure; never {@code null} */ TestIdentifier getTestIdentifier(); /** * Get the {@link Throwable} causing the failure. * * @return the {@link Throwable} for this failure; never {@code null} */ Throwable getException(); } } UniqueIdTrackingListener.java000066400000000000000000000165421455764576500375220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * {@code UniqueIdTrackingListener} is a {@link TestExecutionListener} that tracks * the {@linkplain TestIdentifier#getUniqueId() unique IDs} of all * {@linkplain TestIdentifier#isTest() tests} that were * {@linkplain #executionFinished executed} during the execution of the * {@link TestPlan} and generates a file containing the unique IDs once execution * of the {@code TestPlan} has {@linkplain #testPlanExecutionFinished(TestPlan) * finished}. * *

Tests are tracked regardless of their {@link TestExecutionResult} or whether * they were skipped, and the unique IDs are written to an output file, one ID * per line, encoding using UTF-8. * *

The output file can be used to execute the same set of tests again without * having to query the user configuration for the test plan and without having to * perform test discovery again. This can be useful for test environments such as * within a native image — for example, a GraalVM native image — in * order to rerun the exact same tests from a standard JVM test run within a * native image. * *

Configuration and Defaults

* *

The {@code OUTPUT_DIR} is the directory in which this listener generates * the output file. The exact path of the generated file is * {@code OUTPUT_DIR/OUTPUT_FILE_PREFIX-.txt}, where * {@code } is a pseudo-random number. The inclusion of a random * number in the file name ensures that multiple concurrently executing test * plans do not overwrite each other's results. * *

The value of the {@code OUTPUT_FILE_PREFIX} defaults to * {@link #DEFAULT_OUTPUT_FILE_PREFIX}, but a custom prefix can be set via the * {@link #OUTPUT_FILE_PREFIX_PROPERTY_NAME} configuration property. * *

The {@code OUTPUT_DIR} can be set to a custom directory via the * {@link #OUTPUT_DIR_PROPERTY_NAME} configuration property. Otherwise the * following algorithm is used to select a default output directory. * *

    *
  • If the current working directory of the Java process contains a file named * {@code pom.xml}, the output directory will be {@code ./target}, following the * conventions of Maven.
  • *
  • If the current working directory of the Java process contains a file with * the extension {@code .gradle} or {@code .gradle.kts}, the output directory * will be {@code ./build}, following the conventions of Gradle.
  • *
  • Otherwise, the current working directory of the Java process will be used * as the output directory.
  • *
* *

For example, in a project using Gradle as the build tool, the file generated * by this listener would be {@code ./build/junit-platform-unique-ids-.txt} * by default. * *

Configuration properties can be set via JVM system properties, via a * {@code junit-platform.properties} file in the root of the classpath, or as * JUnit Platform {@linkplain ConfigurationParameters configuration parameters}. * * @since 1.8 */ @API(status = EXPERIMENTAL, since = "1.8") public class UniqueIdTrackingListener implements TestExecutionListener { /** * Property name used to enable the {@code UniqueIdTrackingListener}: {@value} * *

The {@code UniqueIdTrackingListener} is registered automatically via * Java's {@link java.util.ServiceLoader} mechanism but disabled by default. * *

Set the value of this property to {@code true} to enable this listener. */ public static final String LISTENER_ENABLED_PROPERTY_NAME = "junit.platform.listeners.uid.tracking.enabled"; /** * Property name used to set the path to the output directory for the file * generated by the {@code UniqueIdTrackingListener}: {@value} * *

For details on the default output directory, see the * {@linkplain UniqueIdTrackingListener class-level Javadoc}. */ public static final String OUTPUT_DIR_PROPERTY_NAME = "junit.platform.listeners.uid.tracking.output.dir"; /** * Property name used to set the prefix for the name of the file generated * by the {@code UniqueIdTrackingListener}: {@value} * *

Defaults to {@link #DEFAULT_OUTPUT_FILE_PREFIX}. */ public static final String OUTPUT_FILE_PREFIX_PROPERTY_NAME = "junit.platform.listeners.uid.tracking.output.file.prefix"; /** * The default prefix for the name of the file generated by the * {@code UniqueIdTrackingListener}: {@value} * * @see #OUTPUT_FILE_PREFIX_PROPERTY_NAME */ public static final String DEFAULT_OUTPUT_FILE_PREFIX = "junit-platform-unique-ids"; private final Logger logger = LoggerFactory.getLogger(UniqueIdTrackingListener.class); private final List uniqueIds = new ArrayList<>(); private boolean enabled; public UniqueIdTrackingListener() { // to avoid missing-explicit-ctor warning } @Override public void testPlanExecutionStarted(TestPlan testPlan) { this.enabled = testPlan.getConfigurationParameters().getBoolean(LISTENER_ENABLED_PROPERTY_NAME).orElse(false); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { trackTestUid(testIdentifier); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { trackTestUid(testIdentifier); } private void trackTestUid(TestIdentifier testIdentifier) { if (this.enabled && testIdentifier.isTest()) { this.uniqueIds.add(testIdentifier.getUniqueId()); } } @Override public void testPlanExecutionFinished(TestPlan testPlan) { if (this.enabled) { Path outputFile; try { outputFile = createOutputFile(testPlan.getConfigurationParameters()); } catch (Exception ex) { logger.error(ex, () -> "Failed to create output file"); // Abort since we cannot generate the file. return; } logger.debug(() -> "Writing unique IDs to output file " + outputFile.toAbsolutePath()); try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(outputFile, StandardCharsets.UTF_8))) { this.uniqueIds.forEach(writer::println); writer.flush(); } catch (IOException ex) { logger.error(ex, () -> "Failed to write unique IDs to output file " + outputFile.toAbsolutePath()); } } } private Path createOutputFile(ConfigurationParameters configurationParameters) { String prefix = configurationParameters.get(OUTPUT_FILE_PREFIX_PROPERTY_NAME) // .orElse(DEFAULT_OUTPUT_FILE_PREFIX); return OutputDir.create(configurationParameters.get(OUTPUT_DIR_PROPERTY_NAME)) // .createFile(prefix, "txt"); } } discovery/000077500000000000000000000000001455764576500337425ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listenersAbortOnFailureLauncherDiscoveryListener.java000066400000000000000000000040411455764576500445400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.junit.platform.engine.SelectorResolutionResult.Status.FAILED; import static org.junit.platform.engine.SelectorResolutionResult.Status.UNRESOLVED; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; /** * @since 1.6 * @see LauncherDiscoveryListeners#abortOnFailure() */ class AbortOnFailureLauncherDiscoveryListener implements LauncherDiscoveryListener { @Override public void engineDiscoveryFinished(UniqueId engineId, EngineDiscoveryResult result) { result.getThrowable().ifPresent(ExceptionUtils::throwAsUncheckedException); } @Override public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, SelectorResolutionResult result) { if (result.getStatus() == FAILED) { throw new JUnitException(selector + " resolution failed", result.getThrowable().orElse(null)); } if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelector) { UniqueId uniqueId = ((UniqueIdSelector) selector).getUniqueId(); if (uniqueId.hasPrefix(engineId)) { throw new JUnitException(selector + " could not be resolved"); } } } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } return getClass() == obj.getClass(); } @Override public int hashCode() { return 0; } } CompositeLauncherDiscoveryListener.java000066400000000000000000000041721455764576500436330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * @since 1.6 * @see LauncherDiscoveryListeners#composite(List) */ class CompositeLauncherDiscoveryListener implements LauncherDiscoveryListener { private final List listeners; CompositeLauncherDiscoveryListener(List listeners) { this.listeners = Collections.unmodifiableList(new ArrayList<>(listeners)); } @Override public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { listeners.forEach(delegate -> delegate.launcherDiscoveryStarted(request)); } @Override public void launcherDiscoveryFinished(LauncherDiscoveryRequest request) { forEachInReverseOrder(listeners, delegate -> delegate.launcherDiscoveryFinished(request)); } @Override public void engineDiscoveryStarted(UniqueId engineId) { listeners.forEach(delegate -> delegate.engineDiscoveryStarted(engineId)); } @Override public void engineDiscoveryFinished(UniqueId engineId, EngineDiscoveryResult result) { forEachInReverseOrder(listeners, delegate -> delegate.engineDiscoveryFinished(engineId, result)); } @Override public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, SelectorResolutionResult result) { listeners.forEach(delegate -> delegate.selectorProcessed(engineId, selector, result)); } } LauncherDiscoveryListeners.java000066400000000000000000000077451455764576500421440ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import java.util.Arrays; import java.util.List; import java.util.function.Supplier; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.SelectorResolutionResult.Status; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.launcher.LauncherDiscoveryListener; /** * Collection of {@code static} factory methods for creating * {@link LauncherDiscoveryListener LauncherDiscoveryListeners}. * * @since 1.6 */ @API(status = STABLE, since = "1.10") public class LauncherDiscoveryListeners { private LauncherDiscoveryListeners() { } /** * Create a {@link LauncherDiscoveryListener} that aborts test discovery on * failures. * *

The following events are considered failures: * *

    *
  • * a {@linkplain Status#FAILED failed} resolution result. *
  • *
  • * an {@linkplain Status#FAILED unresolved} resolution result for a * {@link UniqueIdSelector} that starts with the engine's unique ID. *
  • *
  • * any recoverable {@link Throwable} thrown by * {@link TestEngine#discover}. *
  • *
*/ public static LauncherDiscoveryListener abortOnFailure() { return new AbortOnFailureLauncherDiscoveryListener(); } /** * Create a {@link LauncherDiscoveryListener} that logs test discovery * events based on their severity. * *

For example, failures during test discovery are logged as errors. */ public static LauncherDiscoveryListener logging() { return new LoggingLauncherDiscoveryListener(); } @API(status = INTERNAL, since = "1.6") public static LauncherDiscoveryListener composite(List listeners) { Preconditions.notNull(listeners, "listeners must not be null"); Preconditions.containsNoNullElements(listeners, "listeners must not contain any null elements"); if (listeners.isEmpty()) { return LauncherDiscoveryListener.NOOP; } if (listeners.size() == 1) { return listeners.get(0); } return new CompositeLauncherDiscoveryListener(listeners); } @API(status = INTERNAL, since = "1.6") public static LauncherDiscoveryListener fromConfigurationParameter(String key, String value) { return Arrays.stream(LauncherDiscoveryListenerType.values()) // .filter(type -> type.parameterValue.equalsIgnoreCase(value)) // .findFirst() // .map(type -> type.creator.get()) // .orElseThrow(() -> newInvalidConfigurationParameterException(key, value)); } private static JUnitException newInvalidConfigurationParameterException(String key, String value) { String allowedValues = Arrays.stream(LauncherDiscoveryListenerType.values()) // .map(type -> type.parameterValue) // .collect(joining("', '", "'", "'")); return new JUnitException("Invalid value of configuration parameter '" + key + "': " // + value + " (allowed are " + allowedValues + ")"); } private enum LauncherDiscoveryListenerType { LOGGING("logging", LauncherDiscoveryListeners::logging), ABORT_ON_FAILURE("abortOnFailure", LauncherDiscoveryListeners::abortOnFailure); private final String parameterValue; private final Supplier creator; LauncherDiscoveryListenerType(String parameterValue, Supplier creator) { this.parameterValue = parameterValue; this.creator = creator; } } } LoggingLauncherDiscoveryListener.java000066400000000000000000000063011455764576500432530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.junit.platform.launcher.EngineDiscoveryResult.Status.FAILED; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Supplier; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * @since 1.6 * @see LauncherDiscoveryListeners#logging() */ class LoggingLauncherDiscoveryListener implements LauncherDiscoveryListener { private static final Logger logger = LoggerFactory.getLogger(LoggingLauncherDiscoveryListener.class); @Override public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { logger.trace(() -> "Test discovery started"); } @Override public void launcherDiscoveryFinished(LauncherDiscoveryRequest request) { logger.trace(() -> "Test discovery finished"); } @Override public void engineDiscoveryStarted(UniqueId engineId) { logger.trace(() -> "Engine " + engineId + " has started discovering tests"); } @Override public void engineDiscoveryFinished(UniqueId engineId, EngineDiscoveryResult result) { if (result.getStatus() == FAILED) { Optional failure = result.getThrowable(); if (failure.isPresent()) { logger.error(failure.get().getCause(), () -> failure.get().getMessage()); } else { logger.error(() -> "Engine " + engineId + " failed to discover tests"); } } else { logger.trace(() -> "Engine " + engineId + " has finished discovering tests"); } } @Override public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, SelectorResolutionResult result) { switch (result.getStatus()) { case RESOLVED: logger.debug(() -> selector + " was resolved by " + engineId); break; case FAILED: logger.error(result.getThrowable().orElse(null), () -> "Resolution of " + selector + " by " + engineId + " failed"); break; case UNRESOLVED: Consumer> loggingConsumer = logger::debug; if (selector instanceof UniqueIdSelector) { UniqueId uniqueId = ((UniqueIdSelector) selector).getUniqueId(); if (uniqueId.hasPrefix(engineId)) { loggingConsumer = logger::warn; } } loggingConsumer.accept(() -> selector + " could not be resolved by " + engineId); break; } } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } return getClass() == obj.getClass(); } @Override public int hashCode() { return 1; } } package-info.java000066400000000000000000000004261455764576500371330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/** * Common {@link org.junit.platform.launcher.LauncherDiscoveryListener} * implementations and factory methods. * * @see org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners * @since 1.6 */ package org.junit.platform.launcher.listeners.discovery; package-info.java000066400000000000000000000004031455764576500351170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/** * Common {@link org.junit.platform.launcher.TestExecutionListener * TestExecutionListener} implementations and related support classes for * the {@link org.junit.platform.launcher.Launcher Launcher}. */ package org.junit.platform.launcher.listeners; junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/000077500000000000000000000000001455764576500334755ustar00rootroot00000000000000CompositeLauncherSessionListener.java000066400000000000000000000024651455764576500427660ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.session; import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; /** * @since 1.8 * @see LauncherSessionListeners#composite(List) */ class CompositeLauncherSessionListener implements LauncherSessionListener { private final List listeners; CompositeLauncherSessionListener(List listeners) { this.listeners = Collections.unmodifiableList(new ArrayList<>(listeners)); } @Override public void launcherSessionOpened(LauncherSession session) { listeners.forEach(delegate -> delegate.launcherSessionOpened(session)); } @Override public void launcherSessionClosed(LauncherSession session) { forEachInReverseOrder(listeners, delegate -> delegate.launcherSessionClosed(session)); } } LauncherSessionListeners.java000066400000000000000000000024541455764576500412640ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.session; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.launcher.LauncherSessionListener; /** * Collection of {@code static} factory methods for creating * {@link LauncherSessionListener LauncherSessionListeners}. * * @since 1.8 */ @API(status = INTERNAL, since = "1.8") public class LauncherSessionListeners { private LauncherSessionListeners() { } public static LauncherSessionListener composite(List listeners) { Preconditions.notNull(listeners, "listeners must not be null"); Preconditions.containsNoNullElements(listeners, "listeners must not contain any null elements"); if (listeners.isEmpty()) { return LauncherSessionListener.NOOP; } if (listeners.size() == 1) { return listeners.get(0); } return new CompositeLauncherSessionListener(listeners); } } package-info.java000066400000000000000000000004161455764576500366060ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/** * Common {@link org.junit.platform.launcher.LauncherSessionListener} * implementations and factory methods. * * @see org.junit.platform.launcher.listeners.session.LauncherSessionListeners * @since 1.8 */ package org.junit.platform.launcher.listeners.session; junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/package-info.java000066400000000000000000000002431455764576500331700ustar00rootroot00000000000000/** * Public API for configuring and launching test plans. * *

This API is typically used by IDEs and build tools. */ package org.junit.platform.launcher; junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/000077500000000000000000000000001455764576500326755ustar00rootroot00000000000000DequeStack.java000066400000000000000000000015201455764576500355100ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import java.util.ArrayDeque; import java.util.Deque; /** * @since 1.1 */ class DequeStack implements Stack { private final Deque deque = new ArrayDeque<>(); @Override public void push(T t) { deque.addFirst(t); } @Override public T peek() { return deque.peek(); } @Override public T pop() { return deque.pollFirst(); } @Override public boolean isEmpty() { return deque.isEmpty(); } @Override public int size() { return deque.size(); } } Operator.java000066400000000000000000000112331455764576500352540ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.junit.platform.launcher.tagexpression.Operator.Associativity.Left; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingOperatorBetween; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingRhsOperand; import static org.junit.platform.launcher.tagexpression.ParseStatus.problemParsing; import static org.junit.platform.launcher.tagexpression.ParseStatus.success; import java.util.function.BiFunction; import java.util.function.Function; /** * @since 1.1 */ class Operator { enum Associativity { Left, Right } interface TagExpressionCreator { ParseStatus createExpressionAndAddTo(Stack> expressions, Token operatorToken); } static Operator nullaryOperator(String representation, int precedence) { return new Operator(representation, precedence, 0, null, (expressions, operatorToken) -> success()); } static Operator unaryOperator(String representation, int precedence, Associativity associativity, Function unaryExpression) { return new Operator(representation, precedence, 1, associativity, (expressions, operatorToken) -> { TokenWith rhs = expressions.pop(); if (operatorToken.isLeftOf(rhs.token)) { Token combinedToken = operatorToken.concatenate(rhs.token); expressions.push(new TokenWith<>(combinedToken, unaryExpression.apply(rhs.element))); return success(); } return missingRhsOperand(operatorToken, representation); }); } static Operator binaryOperator(String representation, int precedence, Associativity associativity, BiFunction binaryExpression) { return new Operator(representation, precedence, 2, associativity, (expressions, operatorToken) -> { TokenWith rhs = expressions.pop(); TokenWith lhs = expressions.pop(); Token lhsToken = lhs.token; if (lhsToken.isLeftOf(operatorToken) && operatorToken.isLeftOf(rhs.token)) { Token combinedToken = lhsToken.concatenate(operatorToken).concatenate(rhs.token); expressions.push(new TokenWith<>(combinedToken, binaryExpression.apply(lhs.element, rhs.element))); return success(); } if (rhs.token.isLeftOf(operatorToken)) { return missingRhsOperand(operatorToken, representation); } if (operatorToken.isLeftOf(lhsToken)) { return missingOperatorBetween(lhs, rhs); } return problemParsing(operatorToken, representation); }); } private final String representation; private final int precedence; private final int arity; private final Associativity associativity; private final TagExpressionCreator tagExpressionCreator; private Operator(String representation, int precedence, int arity, Associativity associativity, TagExpressionCreator tagExpressionCreator) { this.representation = representation; this.precedence = precedence; this.arity = arity; this.associativity = associativity; this.tagExpressionCreator = tagExpressionCreator; } boolean represents(String token) { return representation.equals(token); } String representation() { return representation; } boolean hasLowerPrecedenceThan(Operator operator) { return this.precedence < operator.precedence; } boolean hasSamePrecedenceAs(Operator operator) { return this.precedence == operator.precedence; } boolean isLeftAssociative() { return Left == associativity; } ParseStatus createAndAddExpressionTo(Stack> expressions, Token operatorToken) { if (expressions.size() < arity) { String message = createMissingOperandMessage(expressions, operatorToken); return ParseStatus.errorAt(operatorToken, representation, message); } return tagExpressionCreator.createExpressionAndAddTo(expressions, operatorToken); } private String createMissingOperandMessage(Stack> expressions, Token operatorToken) { if (1 == arity) { return missingOneOperand(associativity == Left ? "lhs" : "rhs"); } if (2 == arity) { int mismatch = arity - expressions.size(); if (2 == mismatch) { return "missing lhs and rhs operand"; } return missingOneOperand(operatorToken.isLeftOf(expressions.peek().token) ? "lhs" : "rhs"); } return "missing operand"; } private String missingOneOperand(String side) { return "missing " + side + " operand"; } } Operators.java000066400000000000000000000025141455764576500354410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static org.junit.platform.launcher.tagexpression.Operator.Associativity.Left; import static org.junit.platform.launcher.tagexpression.Operator.Associativity.Right; import java.util.Map; import java.util.stream.Stream; /** * @since 1.1 */ class Operators { private static final Operator Not = Operator.unaryOperator("!", 3, Right, TagExpressions::not); private static final Operator And = Operator.binaryOperator("&", 2, Left, TagExpressions::and); private static final Operator Or = Operator.binaryOperator("|", 1, Left, TagExpressions::or); private final Map representationToOperator = Stream.of(Not, And, Or).collect( toMap(Operator::representation, identity())); boolean isOperator(String token) { return representationToOperator.containsKey(token); } Operator operatorFor(String token) { return representationToOperator.get(token); } } ParseResult.java000066400000000000000000000031611455764576500357330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Optional; import java.util.function.Function; import org.apiguardian.api.API; /** * The result of attempting to parse a {@link TagExpression}. * *

An instance of this type either contains a successfully parsed * {@link TagExpression} or an error message describing the parse * error. * * @since 1.1 * @see TagExpression#parseFrom(String) */ @API(status = INTERNAL, since = "1.1") public interface ParseResult { /** * Return the parsed {@link TagExpression} or throw an exception with the * contained parse error. * * @param exceptionCreator will be called with the error message in case * this parse result contains a parse error; never {@code null}. */ default TagExpression tagExpressionOrThrow(Function exceptionCreator) { if (errorMessage().isPresent()) { throw exceptionCreator.apply(errorMessage().get()); } return tagExpression().get(); } /** * Return the contained parse error message, if any. */ default Optional errorMessage() { return Optional.empty(); } /** * Return the contained {@link TagExpression}, if any. */ default Optional tagExpression() { return Optional.empty(); } } ParseResults.java000066400000000000000000000015561455764576500361240ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import java.util.Optional; /** * @since 1.1 */ class ParseResults { private ParseResults() { /* no-op */ } static ParseResult success(TagExpression tagExpression) { return new ParseResult() { @Override public Optional tagExpression() { return Optional.of(tagExpression); } }; } static ParseResult error(String errorMessage) { return new ParseResult() { @Override public Optional errorMessage() { return Optional.of(errorMessage); } }; } } ParseStatus.java000066400000000000000000000045171455764576500357460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import java.util.function.Supplier; /** * @since 1.1 */ class ParseStatus { static ParseStatus success() { return error(null); } static ParseStatus problemParsing(Token token, String representation) { return errorAt(token, representation, "problem parsing"); } static ParseStatus missingOpeningParenthesis(Token token, String representation) { return errorAt(token, representation, "missing opening parenthesis"); } static ParseStatus missingClosingParenthesis(Token token, String representation) { return errorAt(token, representation, "missing closing parenthesis"); } static ParseStatus missingRhsOperand(Token token, String representation) { return errorAt(token, representation, "missing rhs operand"); } static ParseStatus errorAt(Token token, String operatorRepresentation, String message) { return error( message + " for '" + operatorRepresentation + "' at index " + format(token.trimmedTokenStartIndex())); } static ParseStatus missingOperatorBetween(TokenWith lhs, TokenWith rhs) { String lhsString = "'" + lhs.element.toString() + "' at index " + format(lhs.token.lastCharacterIndex()); String rhsString = "'" + rhs.element.toString() + "' at index " + format(rhs.token.trimmedTokenStartIndex()); return error("missing operator between " + lhsString + " and " + rhsString); } static ParseStatus emptyTagExpression() { return error("empty tag expression"); } private static String format(int indexInTagExpression) { return "<" + indexInTagExpression + ">"; } private static ParseStatus error(String errorMessage) { return new ParseStatus(errorMessage); } final String errorMessage; private ParseStatus(String errorMessage) { this.errorMessage = errorMessage; } public ParseStatus process(Supplier step) { if (isSuccess()) { return step.get(); } return this; } public boolean isError() { return !isSuccess(); } private boolean isSuccess() { return errorMessage == null; } } Parser.java000066400000000000000000000015201455764576500347130ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import java.util.List; /** * @since 1.1 */ class Parser { private final Tokenizer tokenizer = new Tokenizer(); ParseResult parse(String infixTagExpression) { return constructExpressionFrom(tokensDerivedFrom(infixTagExpression)); } private List tokensDerivedFrom(String infixTagExpression) { return tokenizer.tokenize(infixTagExpression); } private ParseResult constructExpressionFrom(List tokens) { return new ShuntingYard(tokens).execute(); } } ShuntingYard.java000066400000000000000000000127451455764576500361110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static java.lang.Integer.MIN_VALUE; import static org.junit.platform.launcher.tagexpression.Operator.nullaryOperator; import static org.junit.platform.launcher.tagexpression.ParseStatus.emptyTagExpression; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingClosingParenthesis; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingOpeningParenthesis; import static org.junit.platform.launcher.tagexpression.ParseStatus.success; import static org.junit.platform.launcher.tagexpression.TagExpressions.any; import static org.junit.platform.launcher.tagexpression.TagExpressions.none; import static org.junit.platform.launcher.tagexpression.TagExpressions.tag; import java.util.List; /** * This is based on a modified version of the * * Shunting-yard algorithm. * * @since 1.1 */ class ShuntingYard { private static final Operator RightParenthesis = nullaryOperator(")", -1); private static final Operator LeftParenthesis = nullaryOperator("(", -2); private static final Operator Sentinel = nullaryOperator("sentinel", MIN_VALUE); private static final Token SentinelToken = new Token(-1, ""); private final Operators validOperators = new Operators(); private final Stack> expressions = new DequeStack<>(); private final Stack> operators = new DequeStack<>(); private final List tokens; ShuntingYard(List tokens) { this.tokens = tokens; pushOperatorAt(SentinelToken, Sentinel); } public ParseResult execute() { // @formatter:off ParseStatus parseStatus = processTokens() .process(this::consumeRemainingOperators) .process(this::ensureOnlySingleExpressionRemains); // @formatter:on if (parseStatus.isError()) { return ParseResults.error(parseStatus.errorMessage); } return ParseResults.success(expressions.pop().element); } private ParseStatus processTokens() { ParseStatus parseStatus = success(); for (Token token : tokens) { parseStatus = parseStatus.process(() -> process(token)); } return parseStatus; } private ParseStatus process(Token token) { String trimmed = token.string(); if (LeftParenthesis.represents(trimmed)) { pushOperatorAt(token, LeftParenthesis); return success(); } if (RightParenthesis.represents(trimmed)) { return findMatchingLeftParenthesis(token); } if (validOperators.isOperator(trimmed)) { Operator operator = validOperators.operatorFor(trimmed); return findOperands(token, operator); } pushExpressionAt(token, convertLeafTokenToExpression(trimmed)); return success(); } private TagExpression convertLeafTokenToExpression(String trimmed) { if ("any()".equalsIgnoreCase(trimmed)) { return any(); } if ("none()".equalsIgnoreCase(trimmed)) { return none(); } return tag(trimmed); } private ParseStatus findMatchingLeftParenthesis(Token token) { while (!operators.isEmpty()) { TokenWith tokenWithWithOperator = operators.pop(); Operator operator = tokenWithWithOperator.element; if (LeftParenthesis.equals(operator)) { return success(); } ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token); if (parseStatus.isError()) { return parseStatus; } } return missingOpeningParenthesis(token, RightParenthesis.representation()); } private ParseStatus findOperands(Token token, Operator currentOperator) { while (currentOperator.hasLowerPrecedenceThan(previousOperator()) || currentOperator.hasSamePrecedenceAs(previousOperator()) && currentOperator.isLeftAssociative()) { TokenWith tokenWithWithOperator = operators.pop(); ParseStatus parseStatus = tokenWithWithOperator.element.createAndAddExpressionTo(expressions, tokenWithWithOperator.token); if (parseStatus.isError()) { return parseStatus; } } pushOperatorAt(token, currentOperator); return success(); } private Operator previousOperator() { return operators.peek().element; } private void pushExpressionAt(Token token, TagExpression tagExpression) { expressions.push(new TokenWith<>(token, tagExpression)); } private void pushOperatorAt(Token token, Operator operator) { operators.push(new TokenWith<>(token, operator)); } private ParseStatus consumeRemainingOperators() { while (!operators.isEmpty()) { TokenWith tokenWithWithOperator = operators.pop(); Operator operator = tokenWithWithOperator.element; if (LeftParenthesis.equals(operator)) { return missingClosingParenthesis(tokenWithWithOperator.token, operator.representation()); } ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token); if (parseStatus.isError()) { return parseStatus; } } return success(); } private ParseStatus ensureOnlySingleExpressionRemains() { if (expressions.size() == 1) { return success(); } if (expressions.isEmpty()) { return emptyTagExpression(); } TokenWith rhs = expressions.pop(); TokenWith lhs = expressions.pop(); return ParseStatus.missingOperatorBetween(lhs, rhs); } } Stack.java000066400000000000000000000007511455764576500345310ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; /** * @since 1.1 */ interface Stack { void push(T t); T peek(); T pop(); boolean isEmpty(); int size(); } TagExpression.java000066400000000000000000000026561455764576500362650ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Collection; import org.apiguardian.api.API; import org.junit.platform.engine.TestTag; /** * A tag expression can be evaluated against a collection of * {@linkplain TestTag tags} to determine if they match the expression. * * @since 1.1 */ @API(status = INTERNAL, since = "1.1") public interface TagExpression { /** * Attempt to parse a {@link TagExpression} from the supplied tag * expression string. * * @param infixTagExpression the tag expression string to parse; never {@code null}. * @see ParseResult */ @API(status = INTERNAL, since = "1.1") static ParseResult parseFrom(String infixTagExpression) { return new Parser().parse(infixTagExpression); } /** * Evaluate this tag expression against the supplied collection of * {@linkplain TestTag tags}. * * @param tags the tags this tag expression is to be evaluated against * @return {@code true}, if the tags match this tag expression; {@code false}, otherwise */ boolean evaluate(Collection tags); } TagExpressions.java000066400000000000000000000042351455764576500364430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import java.util.Collection; import org.junit.platform.engine.TestTag; /** * @since 1.1 */ class TagExpressions { static TagExpression tag(String tag) { TestTag testTag = TestTag.create(tag); return new TagExpression() { @Override public boolean evaluate(Collection tags) { return tags.contains(testTag); } @Override public String toString() { return testTag.getName(); } }; } static TagExpression none() { return new TagExpression() { @Override public boolean evaluate(Collection tags) { return tags.isEmpty(); } @Override public String toString() { return "none()"; } }; } static TagExpression any() { return new TagExpression() { @Override public boolean evaluate(Collection tags) { return !tags.isEmpty(); } @Override public String toString() { return "any()"; } }; } static TagExpression not(TagExpression toNegate) { return new TagExpression() { @Override public boolean evaluate(Collection tags) { return !toNegate.evaluate(tags); } @Override public String toString() { return "!" + toNegate + ""; } }; } static TagExpression and(TagExpression lhs, TagExpression rhs) { return new TagExpression() { @Override public boolean evaluate(Collection tags) { return lhs.evaluate(tags) && rhs.evaluate(tags); } @Override public String toString() { return "(" + lhs + " & " + rhs + ")"; } }; } static TagExpression or(TagExpression lhs, TagExpression rhs) { return new TagExpression() { @Override public boolean evaluate(Collection tags) { return lhs.evaluate(tags) || rhs.evaluate(tags); } @Override public String toString() { return "(" + lhs + " | " + rhs + ")"; } }; } } Token.java000066400000000000000000000021561455764576500345450ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; /** * @since 1.1 */ class Token { final int startIndex; final String rawString; Token(int startIndex, String rawString) { this.startIndex = startIndex; this.rawString = rawString; } String string() { return rawString.trim(); } public int trimmedTokenStartIndex() { return startIndex + rawString.indexOf(string()); } public boolean isLeftOf(Token token) { return lastCharacterIndex() < token.startIndex; } public int lastCharacterIndex() { return endIndexExclusive() - 1; } public int endIndexExclusive() { return startIndex + rawString.length(); } public Token concatenate(Token rightOfThis) { String concatenatedRawString = this.rawString + rightOfThis.rawString; return new Token(startIndex, concatenatedRawString); } } TokenWith.java000066400000000000000000000010351455764576500353740ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; /** * @since 1.1 */ class TokenWith { final Token token; final T element; TokenWith(Token token, T element) { this.token = token; this.element = element; } } Tokenizer.java000066400000000000000000000021011455764576500354250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static java.util.Collections.emptyList; import static java.util.regex.Pattern.CASE_INSENSITIVE; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @since 1.1 */ class Tokenizer { private static final Pattern PATTERN = Pattern.compile("\\s*(?:(?:(?:any|none)\\(\\))|[()!|&]|(?:[^\\s()!|&]+))", CASE_INSENSITIVE); List tokenize(String infixTagExpression) { if (infixTagExpression == null) { return emptyList(); } List parts = new ArrayList<>(); Matcher matcher = PATTERN.matcher(infixTagExpression); while (matcher.find()) { parts.add(new Token(matcher.start(), matcher.group())); } return parts; } } package-info.java000066400000000000000000000001771455764576500360120ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/** * The tag expression language parser and related support classes. */ package org.junit.platform.launcher.tagexpression; junit5-r5.10.2/junit-platform-launcher/src/main/resources/000077500000000000000000000000001455764576500235265ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/resources/META-INF/000077500000000000000000000000001455764576500246665ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500265115ustar00rootroot00000000000000org.junit.platform.launcher.TestExecutionListener000066400000000000000000000000771455764576500402330ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/main/resources/META-INF/servicesorg.junit.platform.launcher.listeners.UniqueIdTrackingListener junit5-r5.10.2/junit-platform-launcher/src/module/000077500000000000000000000000001455764576500220555ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/module/org.junit.platform.launcher/000077500000000000000000000000001455764576500274175ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java000066400000000000000000000032111455764576500324750ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Public API for configuring and launching test plans. * *

This API is typically used by IDEs and build tools. * * @since 1.0 * @uses org.junit.platform.engine.TestEngine * @uses org.junit.platform.launcher.LauncherDiscoveryListener * @uses org.junit.platform.launcher.LauncherInterceptor * @uses org.junit.platform.launcher.LauncherSessionListener * @uses org.junit.platform.launcher.PostDiscoveryFilter * @uses org.junit.platform.launcher.TestExecutionListener */ module org.junit.platform.launcher { requires transitive java.logging; requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; requires transitive org.junit.platform.engine; exports org.junit.platform.launcher; exports org.junit.platform.launcher.core; exports org.junit.platform.launcher.listeners; exports org.junit.platform.launcher.listeners.discovery; uses org.junit.platform.engine.TestEngine; uses org.junit.platform.launcher.LauncherDiscoveryListener; uses org.junit.platform.launcher.LauncherInterceptor; uses org.junit.platform.launcher.LauncherSessionListener; uses org.junit.platform.launcher.PostDiscoveryFilter; uses org.junit.platform.launcher.TestExecutionListener; provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.launcher.listeners.UniqueIdTrackingListener; } junit5-r5.10.2/junit-platform-launcher/src/testFixtures/000077500000000000000000000000001455764576500233015ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/000077500000000000000000000000001455764576500242225ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/000077500000000000000000000000001455764576500250115ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500261425ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/platform/000077500000000000000000000000001455764576500277665ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/platform/launcher/000077500000000000000000000000001455764576500315675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/platform/launcher/core/000077500000000000000000000000001455764576500325175ustar00rootroot00000000000000ConfigurationParametersFactoryForTests.java000066400000000000000000000014221455764576500431570ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import java.util.Map; import org.junit.platform.engine.ConfigurationParameters; public class ConfigurationParametersFactoryForTests { private ConfigurationParametersFactoryForTests() { } public static ConfigurationParameters create(Map configParams) { return LauncherConfigurationParameters.builder() // .explicitParameters(configParams) // .enableImplicitProviders(false) // .build(); } } LauncherFactoryForTestingPurposesOnly.java000066400000000000000000000022041455764576500430020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-launcher/src/testFixtures/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.Launcher; /** * @since 1.0 */ public class LauncherFactoryForTestingPurposesOnly { public static Launcher createLauncher(TestEngine... engines) { return LauncherFactory.create(createLauncherConfigBuilderWithDisabledServiceLoading() // .addTestEngines(engines) // .build()); } public static LauncherConfig.Builder createLauncherConfigBuilderWithDisabledServiceLoading() { return LauncherConfig.builder() // .enableTestEngineAutoRegistration(false) // .enableLauncherDiscoveryListenerAutoRegistration(false) // .enableTestExecutionListenerAutoRegistration(false) // .enablePostDiscoveryFilterAutoRegistration(false) // .enableLauncherSessionListenerAutoRegistration(false); } } junit5-r5.10.2/junit-platform-reporting/000077500000000000000000000000001455764576500202115ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/LICENSE-open-test-reporting.md000066400000000000000000000243621455764576500255470ustar00rootroot00000000000000Apache License ============== _Version 2.0, January 2004_ _<>_ ### Terms and Conditions for use, reproduction, and distribution #### 1. Definitions “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. #### 2. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. #### 3. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. #### 4. Redistribution You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: * **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and * **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and * **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. #### 5. Submission of Contributions Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. #### 6. Trademarks This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. #### 7. Disclaimer of Warranty Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) 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. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. #### 8. Limitation of Liability In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. #### 9. Accepting Warranty or Additional Liability While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. _END OF TERMS AND CONDITIONS_ ### APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets `[]` replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed 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 https://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. junit5-r5.10.2/junit-platform-reporting/junit-platform-reporting.gradle.kts000066400000000000000000000014461455764576500271600ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") id("junitbuild.shadow-conventions") } description = "JUnit Platform Reporting" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) shadowed(libs.openTestReporting.events) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks { shadowJar { relocate("org.opentest4j.reporting", "org.junit.platform.reporting.shadow.org.opentest4j.reporting") from(projectDir) { include("LICENSE-open-test-reporting.md") into("META-INF") } } compileModule { options.compilerArgs.addAll(listOf( "--add-modules", "org.opentest4j.reporting.events", "--add-reads", "${javaModuleName}=org.opentest4j.reporting.events" )) } } junit5-r5.10.2/junit-platform-reporting/src/000077500000000000000000000000001455764576500210005ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/000077500000000000000000000000001455764576500217245ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/000077500000000000000000000000001455764576500226455ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/000077500000000000000000000000001455764576500234345ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/000077500000000000000000000000001455764576500245655ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500264115ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/000077500000000000000000000000001455764576500304225ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/000077500000000000000000000000001455764576500316665ustar00rootroot00000000000000LegacyReportingUtils.java000066400000000000000000000037751455764576500366050ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Utility methods for dealing with legacy reporting infrastructure, such as * reporting systems built on the Ant-based XML reporting format for JUnit 4. * * This class was formerly from {@code junit-platform-launcher} * in {@link org.junit.platform.launcher.listeners} package. * * @since 1.0.3 */ @API(status = MAINTAINED, since = "1.6") public final class LegacyReportingUtils { private LegacyReportingUtils() { /* no-op */ } /** * Get the class name for the supplied {@link TestIdentifier} using the * supplied {@link TestPlan}. * *

This implementation attempts to find the closest test identifier with * a {@link ClassSource} by traversing the hierarchy upwards towards the * root starting with the supplied test identifier. In case no such source * is found, it falls back to using the parent's * {@linkplain TestIdentifier#getLegacyReportingName legacy reporting name}. * * @param testPlan the test plan that contains the {@code TestIdentifier}; * never {@code null} * @param testIdentifier the identifier to determine the class name for; * never {@code null} * @see TestIdentifier#getLegacyReportingName */ @SuppressWarnings("deprecation") public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifier) { return org.junit.platform.launcher.listeners.LegacyReportingUtils.getClassName(testPlan, testIdentifier); } } package-info.java000066400000000000000000000001371455764576500347770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/** * Support for legacy reporting formats. */ package org.junit.platform.reporting.legacy; junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/000077500000000000000000000000001455764576500324665ustar00rootroot00000000000000LegacyXmlReportGeneratingListener.java000066400000000000000000000101601455764576500420430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static org.apiguardian.api.API.Status.STABLE; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Clock; import javax.xml.stream.XMLStreamException; import org.apiguardian.api.API; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * {@code LegacyXmlReportGeneratingListener} is a {@link TestExecutionListener} that * generates a separate XML report for each {@linkplain TestPlan#getRoots() root} * in the {@link TestPlan}. * *

Note that the generated XML format is compatible with the legacy * de facto standard for JUnit 4 based test reports that was made popular by the * Ant build system. * * @since 1.4 * @see org.junit.platform.launcher.listeners.LoggingListener * @see org.junit.platform.launcher.listeners.SummaryGeneratingListener */ @API(status = STABLE, since = "1.7") public class LegacyXmlReportGeneratingListener implements TestExecutionListener { private final Path reportsDir; private final PrintWriter out; private final Clock clock; private XmlReportData reportData; public LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out) { this(reportsDir, out, Clock.systemDefaultZone()); } // For tests only LegacyXmlReportGeneratingListener(String reportsDir, PrintWriter out, Clock clock) { this(Paths.get(reportsDir), out, clock); } private LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out, Clock clock) { this.reportsDir = reportsDir; this.out = out; this.clock = clock; } @Override public void testPlanExecutionStarted(TestPlan testPlan) { this.reportData = new XmlReportData(testPlan, clock); try { Files.createDirectories(this.reportsDir); } catch (IOException e) { printException("Could not create reports directory: " + this.reportsDir, e); } } @Override public void testPlanExecutionFinished(TestPlan testPlan) { this.reportData = null; } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { this.reportData.markSkipped(testIdentifier, reason); writeXmlReportInCaseOfRoot(testIdentifier); } @Override public void executionStarted(TestIdentifier testIdentifier) { this.reportData.markStarted(testIdentifier); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { this.reportData.addReportEntry(testIdentifier, entry); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult result) { this.reportData.markFinished(testIdentifier, result); writeXmlReportInCaseOfRoot(testIdentifier); } private void writeXmlReportInCaseOfRoot(TestIdentifier testIdentifier) { if (isRoot(testIdentifier)) { String rootName = testIdentifier.getUniqueIdObject().getSegments().get(0).getValue(); writeXmlReportSafely(testIdentifier, rootName); } } private void writeXmlReportSafely(TestIdentifier testIdentifier, String rootName) { Path xmlFile = this.reportsDir.resolve("TEST-" + rootName + ".xml"); try (Writer fileWriter = Files.newBufferedWriter(xmlFile)) { new XmlReportWriter(this.reportData).writeXmlReport(testIdentifier, fileWriter); } catch (XMLStreamException | IOException e) { printException("Could not write XML report: " + xmlFile, e); } } private boolean isRoot(TestIdentifier testIdentifier) { return !testIdentifier.getParentIdObject().isPresent(); } private void printException(String message, Exception exception) { out.println(message); exception.printStackTrace(out); } } XmlReportData.java000066400000000000000000000112371455764576500360040ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.4 */ class XmlReportData { private static final int MILLIS_PER_SECOND = 1000; private final Map finishedTests = new ConcurrentHashMap<>(); private final Map skippedTests = new ConcurrentHashMap<>(); private final Map startInstants = new ConcurrentHashMap<>(); private final Map endInstants = new ConcurrentHashMap<>(); private final Map> reportEntries = new ConcurrentHashMap<>(); private final TestPlan testPlan; private final Clock clock; XmlReportData(TestPlan testPlan, Clock clock) { this.testPlan = testPlan; this.clock = clock; } TestPlan getTestPlan() { return this.testPlan; } Clock getClock() { return this.clock; } void markSkipped(TestIdentifier testIdentifier, String reason) { this.skippedTests.put(testIdentifier, reason == null ? "" : reason); } void markStarted(TestIdentifier testIdentifier) { this.startInstants.put(testIdentifier, this.clock.instant()); } void markFinished(TestIdentifier testIdentifier, TestExecutionResult result) { this.endInstants.put(testIdentifier, this.clock.instant()); if (result.getStatus() == ABORTED) { String reason = result.getThrowable().map(ExceptionUtils::readStackTrace).orElse(""); this.skippedTests.put(testIdentifier, reason); } else { this.finishedTests.put(testIdentifier, result); } } void addReportEntry(TestIdentifier testIdentifier, ReportEntry entry) { List entries = this.reportEntries.computeIfAbsent(testIdentifier, key -> new ArrayList<>()); entries.add(entry); } boolean wasSkipped(TestIdentifier testIdentifier) { return findSkippedAncestor(testIdentifier).isPresent(); } double getDurationInSeconds(TestIdentifier testIdentifier) { Instant startInstant = this.startInstants.getOrDefault(testIdentifier, Instant.EPOCH); Instant endInstant = this.endInstants.getOrDefault(testIdentifier, startInstant); return Duration.between(startInstant, endInstant).toMillis() / (double) MILLIS_PER_SECOND; } String getSkipReason(TestIdentifier testIdentifier) { return findSkippedAncestor(testIdentifier).map(skippedTestIdentifier -> { String reason = this.skippedTests.get(skippedTestIdentifier); if (!testIdentifier.equals(skippedTestIdentifier)) { reason = "parent was skipped: " + reason; } return reason; }).orElse(null); } List getResults(TestIdentifier testIdentifier) { return getAncestors(testIdentifier).stream() // .map(this.finishedTests::get) // .filter(Objects::nonNull) // .collect(toList()); } List getReportEntries(TestIdentifier testIdentifier) { return this.reportEntries.getOrDefault(testIdentifier, emptyList()); } private Optional findSkippedAncestor(TestIdentifier testIdentifier) { return findAncestor(testIdentifier, this.skippedTests::containsKey); } private Optional findAncestor(TestIdentifier testIdentifier, Predicate predicate) { Optional current = Optional.of(testIdentifier); while (current.isPresent()) { if (predicate.test(current.get())) { return current; } current = this.testPlan.getParent(current.get()); } return Optional.empty(); } private List getAncestors(TestIdentifier testIdentifier) { TestIdentifier current = testIdentifier; List ancestors = new ArrayList<>(); while (current != null) { ancestors.add(current); current = this.testPlan.getParent(current).orElse(null); } return ancestors; } } XmlReportWriter.java000066400000000000000000000371501455764576500364110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static java.text.MessageFormat.format; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; import static java.util.Collections.emptyList; import static java.util.Comparator.naturalOrder; import static java.util.function.Function.identity; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.junit.platform.commons.util.ExceptionUtils.readStackTrace; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.LauncherConstants.STDOUT_REPORT_ENTRY_KEY; import static org.junit.platform.reporting.legacy.xml.XmlReportWriter.AggregatedTestResult.Type.ERROR; import static org.junit.platform.reporting.legacy.xml.XmlReportWriter.AggregatedTestResult.Type.FAILURE; import static org.junit.platform.reporting.legacy.xml.XmlReportWriter.AggregatedTestResult.Type.SKIPPED; import static org.junit.platform.reporting.legacy.xml.XmlReportWriter.AggregatedTestResult.Type.SUCCESS; import java.io.Writer; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.NumberFormat; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Properties; import java.util.TreeSet; import java.util.regex.Pattern; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.reporting.legacy.LegacyReportingUtils; import org.junit.platform.reporting.legacy.xml.XmlReportWriter.AggregatedTestResult.Type; /** * {@code XmlReportWriter} writes an XML report whose format is compatible * with the de facto standard for JUnit 4 based test reports that was made * popular by the Ant build system. * * @since 1.4 */ class XmlReportWriter { // Using zero-width assertions in the split pattern simplifies the splitting process: All split parts // (including the first and last one) can be used directly, without having to re-add separator characters. private static final Pattern CDATA_SPLIT_PATTERN = Pattern.compile("(?<=]])(?=>)"); private final XmlReportData reportData; XmlReportWriter(XmlReportData reportData) { this.reportData = reportData; } void writeXmlReport(TestIdentifier rootDescriptor, Writer out) throws XMLStreamException { TestPlan testPlan = this.reportData.getTestPlan(); Map tests = testPlan.getDescendants(rootDescriptor) // .stream() // .filter(testIdentifier -> shouldInclude(testPlan, testIdentifier)) // .collect(toMap(identity(), this::toAggregatedResult)); // writeXmlReport(rootDescriptor, tests, out); } private AggregatedTestResult toAggregatedResult(TestIdentifier testIdentifier) { if (this.reportData.wasSkipped(testIdentifier)) { return AggregatedTestResult.skipped(); } return AggregatedTestResult.nonSkipped(this.reportData.getResults(testIdentifier)); } private boolean shouldInclude(TestPlan testPlan, TestIdentifier testIdentifier) { return testIdentifier.isTest() || testPlan.getChildren(testIdentifier).isEmpty(); } private void writeXmlReport(TestIdentifier testIdentifier, Map tests, Writer out) throws XMLStreamException { XMLOutputFactory factory = XMLOutputFactory.newInstance(); XMLStreamWriter xmlWriter = factory.createXMLStreamWriter(out); xmlWriter.writeStartDocument("UTF-8", "1.0"); newLine(xmlWriter); writeTestsuite(testIdentifier, tests, xmlWriter); xmlWriter.writeEndDocument(); xmlWriter.flush(); xmlWriter.close(); } private void writeTestsuite(TestIdentifier testIdentifier, Map tests, XMLStreamWriter writer) throws XMLStreamException { // NumberFormat is not thread-safe. Thus, we instantiate it here and pass it to // writeTestcase instead of using a constant NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); writer.writeStartElement("testsuite"); writeSuiteAttributes(testIdentifier, tests.values(), numberFormat, writer); newLine(writer); writeSystemProperties(writer); for (Entry entry : tests.entrySet()) { writeTestcase(entry.getKey(), entry.getValue(), numberFormat, writer); } writeOutputElement("system-out", formatNonStandardAttributesAsString(testIdentifier), writer); writer.writeEndElement(); newLine(writer); } private void writeSuiteAttributes(TestIdentifier testIdentifier, Collection testResults, NumberFormat numberFormat, XMLStreamWriter writer) throws XMLStreamException { writeAttributeSafely(writer, "name", testIdentifier.getDisplayName()); writeTestCounts(testResults, writer); writeAttributeSafely(writer, "time", getTime(testIdentifier, numberFormat)); writeAttributeSafely(writer, "hostname", getHostname().orElse("")); writeAttributeSafely(writer, "timestamp", ISO_LOCAL_DATE_TIME.format(getCurrentDateTime())); } private void writeTestCounts(Collection testResults, XMLStreamWriter writer) throws XMLStreamException { Map counts = testResults.stream().map(it -> it.type).collect(groupingBy(identity(), counting())); long total = counts.values().stream().mapToLong(Long::longValue).sum(); writeAttributeSafely(writer, "tests", String.valueOf(total)); writeAttributeSafely(writer, "skipped", counts.getOrDefault(SKIPPED, 0L).toString()); writeAttributeSafely(writer, "failures", counts.getOrDefault(FAILURE, 0L).toString()); writeAttributeSafely(writer, "errors", counts.getOrDefault(ERROR, 0L).toString()); } private void writeSystemProperties(XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement("properties"); newLine(writer); Properties systemProperties = System.getProperties(); for (String propertyName : new TreeSet<>(systemProperties.stringPropertyNames())) { writer.writeEmptyElement("property"); writeAttributeSafely(writer, "name", propertyName); writeAttributeSafely(writer, "value", systemProperties.getProperty(propertyName)); newLine(writer); } writer.writeEndElement(); newLine(writer); } private void writeTestcase(TestIdentifier testIdentifier, AggregatedTestResult testResult, NumberFormat numberFormat, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement("testcase"); writeAttributeSafely(writer, "name", getName(testIdentifier)); writeAttributeSafely(writer, "classname", getClassName(testIdentifier)); writeAttributeSafely(writer, "time", getTime(testIdentifier, numberFormat)); newLine(writer); writeSkippedOrErrorOrFailureElement(testIdentifier, testResult, writer); List systemOutElements = new ArrayList<>(); List systemErrElements = new ArrayList<>(); systemOutElements.add(formatNonStandardAttributesAsString(testIdentifier)); collectReportEntries(testIdentifier, systemOutElements, systemErrElements); writeOutputElements("system-out", systemOutElements, writer); writeOutputElements("system-err", systemErrElements, writer); writer.writeEndElement(); newLine(writer); } private String getName(TestIdentifier testIdentifier) { return testIdentifier.getLegacyReportingName(); } private String getClassName(TestIdentifier testIdentifier) { return LegacyReportingUtils.getClassName(this.reportData.getTestPlan(), testIdentifier); } private void writeSkippedOrErrorOrFailureElement(TestIdentifier testIdentifier, AggregatedTestResult testResult, XMLStreamWriter writer) throws XMLStreamException { if (testResult.type == SKIPPED) { writeSkippedElement(this.reportData.getSkipReason(testIdentifier), writer); } else { Map>> throwablesByType = testResult.getThrowablesByType(); for (Type type : EnumSet.of(FAILURE, ERROR)) { for (Optional throwable : throwablesByType.getOrDefault(type, emptyList())) { writeErrorOrFailureElement(type, throwable.orElse(null), writer); } } } } private void writeSkippedElement(String reason, XMLStreamWriter writer) throws XMLStreamException { if (isNotBlank(reason)) { writer.writeStartElement("skipped"); writeCDataSafely(writer, reason); writer.writeEndElement(); } else { writer.writeEmptyElement("skipped"); } newLine(writer); } private void writeErrorOrFailureElement(Type type, Throwable throwable, XMLStreamWriter writer) throws XMLStreamException { String elementName = type == FAILURE ? "failure" : "error"; if (throwable != null) { writer.writeStartElement(elementName); writeFailureAttributesAndContent(throwable, writer); writer.writeEndElement(); } else { writer.writeEmptyElement(elementName); } newLine(writer); } private void writeFailureAttributesAndContent(Throwable throwable, XMLStreamWriter writer) throws XMLStreamException { if (throwable.getMessage() != null) { writeAttributeSafely(writer, "message", throwable.getMessage()); } writeAttributeSafely(writer, "type", throwable.getClass().getName()); writeCDataSafely(writer, readStackTrace(throwable)); } private void collectReportEntries(TestIdentifier testIdentifier, List systemOutElements, List systemErrElements) { List entries = this.reportData.getReportEntries(testIdentifier); if (!entries.isEmpty()) { List systemOutElementsForCapturedOutput = new ArrayList<>(); StringBuilder formattedReportEntries = new StringBuilder(); for (int i = 0; i < entries.size(); i++) { ReportEntry reportEntry = entries.get(i); Map keyValuePairs = new LinkedHashMap<>(reportEntry.getKeyValuePairs()); removeIfPresentAndAddAsSeparateElement(keyValuePairs, STDOUT_REPORT_ENTRY_KEY, systemOutElementsForCapturedOutput); removeIfPresentAndAddAsSeparateElement(keyValuePairs, STDERR_REPORT_ENTRY_KEY, systemErrElements); if (!keyValuePairs.isEmpty()) { buildReportEntryDescription(reportEntry.getTimestamp(), keyValuePairs, i + 1, formattedReportEntries); } } systemOutElements.add(formattedReportEntries.toString().trim()); systemOutElements.addAll(systemOutElementsForCapturedOutput); } } private void removeIfPresentAndAddAsSeparateElement(Map keyValuePairs, String key, List elements) { String value = keyValuePairs.remove(key); if (value != null) { elements.add(value); } } private void buildReportEntryDescription(LocalDateTime timestamp, Map keyValuePairs, int entryNumber, StringBuilder result) { result.append( format("Report Entry #{0} (timestamp: {1})\n", entryNumber, ISO_LOCAL_DATE_TIME.format(timestamp))); keyValuePairs.forEach((key, value) -> result.append(format("\t- {0}: {1}\n", key, value))); } private String getTime(TestIdentifier testIdentifier, NumberFormat numberFormat) { return numberFormat.format(this.reportData.getDurationInSeconds(testIdentifier)); } private Optional getHostname() { try { return Optional.ofNullable(InetAddress.getLocalHost().getHostName()); } catch (UnknownHostException e) { return Optional.empty(); } } private LocalDateTime getCurrentDateTime() { return LocalDateTime.now(this.reportData.getClock()).withNano(0); } private String formatNonStandardAttributesAsString(TestIdentifier testIdentifier) { return "unique-id: " + testIdentifier.getUniqueId() // + "\ndisplay-name: " + testIdentifier.getDisplayName(); } private void writeOutputElements(String elementName, List elements, XMLStreamWriter writer) throws XMLStreamException { for (String content : elements) { writeOutputElement(elementName, content, writer); } } private void writeOutputElement(String elementName, String content, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement(elementName); writeCDataSafely(writer, "\n" + content + "\n"); writer.writeEndElement(); newLine(writer); } private void writeAttributeSafely(XMLStreamWriter writer, String name, String value) throws XMLStreamException { writer.writeAttribute(name, escapeIllegalChars(value)); } private void writeCDataSafely(XMLStreamWriter writer, String data) throws XMLStreamException { for (String safeDataPart : CDATA_SPLIT_PATTERN.split(escapeIllegalChars(data))) { writer.writeCData(safeDataPart); } } static String escapeIllegalChars(String text) { if (text.codePoints().allMatch(XmlReportWriter::isAllowedXmlCharacter)) { return text; } StringBuilder result = new StringBuilder(text.length() * 2); text.codePoints().forEach(codePoint -> { if (isAllowedXmlCharacter(codePoint)) { result.appendCodePoint(codePoint); } else { // use a Character Reference (cf. https://www.w3.org/TR/xml/#NT-CharRef) result.append("&#").append(codePoint).append(';'); } }); return result.toString(); } private static boolean isAllowedXmlCharacter(int codePoint) { // source: https://www.w3.org/TR/xml/#charsets return codePoint == 0x9 // || codePoint == 0xA // || codePoint == 0xD // || (codePoint >= 0x20 && codePoint <= 0xD7FF) // || (codePoint >= 0xE000 && codePoint <= 0xFFFD) // || (codePoint >= 0x10000 && codePoint <= 0x10FFFF); } private void newLine(XMLStreamWriter xmlWriter) throws XMLStreamException { xmlWriter.writeCharacters("\n"); } private static boolean isFailure(TestExecutionResult result) { Optional throwable = result.getThrowable(); return throwable.isPresent() && throwable.get() instanceof AssertionError; } static class AggregatedTestResult { private static final AggregatedTestResult SKIPPED_RESULT = new AggregatedTestResult(SKIPPED, emptyList()); public static AggregatedTestResult skipped() { return SKIPPED_RESULT; } public static AggregatedTestResult nonSkipped(List executionResults) { Type type = executionResults.stream() // .map(Type::from) // .max(naturalOrder()) // .orElse(SUCCESS); return new AggregatedTestResult(type, executionResults); } private final Type type; private final List executionResults; private AggregatedTestResult(Type type, List executionResults) { this.type = type; this.executionResults = executionResults; } public Map>> getThrowablesByType() { return executionResults.stream() // .collect(groupingBy(Type::from, mapping(TestExecutionResult::getThrowable, toList()))); } enum Type { SUCCESS, SKIPPED, FAILURE, ERROR; private static Type from(TestExecutionResult executionResult) { if (executionResult.getStatus() == FAILED) { return isFailure(executionResult) ? FAILURE : ERROR; } return SUCCESS; } } } } package-info.java000066400000000000000000000003621455764576500355770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/** * Support for generating XML reports using a format which is compatible with * the de facto standard for JUnit 4 based test reports that was made popular * by the Ant build system. */ package org.junit.platform.reporting.legacy.xml; junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/000077500000000000000000000000001455764576500313635ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/000077500000000000000000000000001455764576500321635ustar00rootroot00000000000000JUnitFactory.java000066400000000000000000000020231455764576500353250ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import org.junit.platform.engine.TestDescriptor; import org.opentest4j.reporting.events.api.Factory; import org.opentest4j.reporting.schema.Namespace; class JUnitFactory { static Namespace NAMESPACE = Namespace.of("https://schemas.junit.org/open-test-reporting"); private JUnitFactory() { } static Factory uniqueId(String uniqueId) { return context -> new UniqueId(context, uniqueId); } static Factory legacyReportingName(String legacyReportingName) { return context -> new LegacyReportingName(context, legacyReportingName); } static Factory type(TestDescriptor.Type type) { return context -> new Type(context, type); } } LegacyReportingName.java000066400000000000000000000015521455764576500366510ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import org.opentest4j.reporting.events.api.ChildElement; import org.opentest4j.reporting.events.api.Context; import org.opentest4j.reporting.events.core.Metadata; import org.opentest4j.reporting.schema.QualifiedName; class LegacyReportingName extends ChildElement { static final QualifiedName ELEMENT = QualifiedName.of(JUnitFactory.NAMESPACE, "legacyReportingName"); LegacyReportingName(Context context, String value) { super(context, ELEMENT); withContent(value); } } OpenTestReportGeneratingListener.java000066400000000000000000000270221455764576500414210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.junit.platform.reporting.open.xml.JUnitFactory.legacyReportingName; import static org.junit.platform.reporting.open.xml.JUnitFactory.type; import static org.junit.platform.reporting.open.xml.JUnitFactory.uniqueId; import static org.opentest4j.reporting.events.core.CoreFactory.attachments; import static org.opentest4j.reporting.events.core.CoreFactory.cpuCores; import static org.opentest4j.reporting.events.core.CoreFactory.data; import static org.opentest4j.reporting.events.core.CoreFactory.directorySource; import static org.opentest4j.reporting.events.core.CoreFactory.fileSource; import static org.opentest4j.reporting.events.core.CoreFactory.hostName; import static org.opentest4j.reporting.events.core.CoreFactory.infrastructure; import static org.opentest4j.reporting.events.core.CoreFactory.metadata; import static org.opentest4j.reporting.events.core.CoreFactory.operatingSystem; import static org.opentest4j.reporting.events.core.CoreFactory.reason; import static org.opentest4j.reporting.events.core.CoreFactory.result; import static org.opentest4j.reporting.events.core.CoreFactory.sources; import static org.opentest4j.reporting.events.core.CoreFactory.tag; import static org.opentest4j.reporting.events.core.CoreFactory.tags; import static org.opentest4j.reporting.events.core.CoreFactory.uriSource; import static org.opentest4j.reporting.events.core.CoreFactory.userName; import static org.opentest4j.reporting.events.java.JavaFactory.classSource; import static org.opentest4j.reporting.events.java.JavaFactory.classpathResourceSource; import static org.opentest4j.reporting.events.java.JavaFactory.fileEncoding; import static org.opentest4j.reporting.events.java.JavaFactory.heapSize; import static org.opentest4j.reporting.events.java.JavaFactory.javaVersion; import static org.opentest4j.reporting.events.java.JavaFactory.methodSource; import static org.opentest4j.reporting.events.java.JavaFactory.packageSource; import static org.opentest4j.reporting.events.java.JavaFactory.throwable; import static org.opentest4j.reporting.events.root.RootFactory.finished; import static org.opentest4j.reporting.events.root.RootFactory.reported; import static org.opentest4j.reporting.events.root.RootFactory.started; import java.io.IOException; import java.io.UncheckedIOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.file.Path; import java.time.Instant; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.ClasspathResourceSource; import org.junit.platform.engine.support.descriptor.CompositeTestSource; import org.junit.platform.engine.support.descriptor.DirectorySource; import org.junit.platform.engine.support.descriptor.FileSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.engine.support.descriptor.PackageSource; import org.junit.platform.engine.support.descriptor.UriSource; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.listeners.OutputDir; import org.opentest4j.reporting.events.api.DocumentWriter; import org.opentest4j.reporting.events.api.NamespaceRegistry; import org.opentest4j.reporting.events.core.Result; import org.opentest4j.reporting.events.core.Sources; import org.opentest4j.reporting.events.root.Events; import org.opentest4j.reporting.schema.Namespace; /** * Open Test Reporting events XML generating test execution listener. * * @since 1.9 */ @API(status = EXPERIMENTAL, since = "1.9") public class OpenTestReportGeneratingListener implements TestExecutionListener { static final String ENABLED_PROPERTY_NAME = "junit.platform.reporting.open.xml.enabled"; static final String OUTPUT_DIR_PROPERTY_NAME = "junit.platform.reporting.output.dir"; private final AtomicInteger idCounter = new AtomicInteger(); private final Map inProgressIds = new ConcurrentHashMap<>(); private DocumentWriter eventsFileWriter = DocumentWriter.noop(); public OpenTestReportGeneratingListener() { } @Override public void testPlanExecutionStarted(TestPlan testPlan) { ConfigurationParameters config = testPlan.getConfigurationParameters(); if (isEnabled(config)) { NamespaceRegistry namespaceRegistry = NamespaceRegistry.builder(Namespace.REPORTING_CORE) // .add("e", Namespace.REPORTING_EVENTS) // .add("java", Namespace.REPORTING_JAVA) // .add("junit", JUnitFactory.NAMESPACE, "https://junit.org/junit5/schemas/open-test-reporting/junit-1.9.xsd") // .build(); Path eventsXml = OutputDir.create(config.get(OUTPUT_DIR_PROPERTY_NAME)) // .createFile("junit-platform-events", "xml"); try { eventsFileWriter = Events.createDocumentWriter(namespaceRegistry, eventsXml); reportInfrastructure(); } catch (Exception e) { throw new JUnitException("Failed to initialize XML events file: " + eventsXml, e); } } } private Boolean isEnabled(ConfigurationParameters config) { return config.getBoolean(ENABLED_PROPERTY_NAME).orElse(false); } private void reportInfrastructure() { eventsFileWriter.append(infrastructure(), infrastructure -> { try { String hostName = InetAddress.getLocalHost().getHostName(); infrastructure.append(hostName(hostName)); } catch (UnknownHostException ignored) { } infrastructure // .append(userName(System.getProperty("user.name"))) // .append(operatingSystem(System.getProperty("os.name"))) // .append(cpuCores(Runtime.getRuntime().availableProcessors())) // .append(javaVersion(System.getProperty("java.version"))) // .append(fileEncoding(System.getProperty("file.encoding"))) // .append(heapSize(), heapSize -> heapSize.withMax(Runtime.getRuntime().maxMemory())); }); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { try { eventsFileWriter.close(); } catch (IOException e) { throw new UncheckedIOException("Failed to close XML events file", e); } finally { eventsFileWriter = DocumentWriter.noop(); } } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { String id = String.valueOf(idCounter.incrementAndGet()); reportStarted(testIdentifier, id); eventsFileWriter.append(finished(id, Instant.now()), // finished -> finished.append(result(Result.Status.SKIPPED), result -> { if (StringUtils.isNotBlank(reason)) { result.append(reason(reason)); } })); } @Override public void executionStarted(TestIdentifier testIdentifier) { String id = String.valueOf(idCounter.incrementAndGet()); inProgressIds.put(testIdentifier.getUniqueIdObject(), id); reportStarted(testIdentifier, id); } private void reportStarted(TestIdentifier testIdentifier, String id) { eventsFileWriter.append(started(id, Instant.now(), testIdentifier.getDisplayName()), started -> { testIdentifier.getParentIdObject().ifPresent(parentId -> started.withParentId(inProgressIds.get(parentId))); started.append(metadata(), metadata -> { if (!testIdentifier.getTags().isEmpty()) { metadata.append(tags(), tags -> // testIdentifier.getTags().forEach(tag -> tags.append(tag(tag.getName())))); } metadata.append(uniqueId(testIdentifier.getUniqueId())) // .append(legacyReportingName(testIdentifier.getLegacyReportingName())) // .append(type(testIdentifier.getType())); }); testIdentifier.getSource().ifPresent( source -> started.append(sources(), sources -> addTestSource(source, sources))); }); } private void addTestSource(TestSource source, Sources sources) { if (source instanceof CompositeTestSource) { ((CompositeTestSource) source).getSources().forEach(it -> addTestSource(it, sources)); } else if (source instanceof ClassSource) { ClassSource classSource = (ClassSource) source; sources.append(classSource(classSource.getClassName()), // element -> classSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } else if (source instanceof MethodSource) { MethodSource methodSource = (MethodSource) source; sources.append(methodSource(methodSource.getClassName(), methodSource.getMethodName()), element -> { String methodParameterTypes = methodSource.getMethodParameterTypes(); if (methodParameterTypes != null) { element.withMethodParameterTypes(methodParameterTypes); } }); } else if (source instanceof ClasspathResourceSource) { ClasspathResourceSource classpathResourceSource = (ClasspathResourceSource) source; sources.append(classpathResourceSource(classpathResourceSource.getClasspathResourceName()), // element -> classpathResourceSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } else if (source instanceof PackageSource) { sources.append(packageSource(((PackageSource) source).getPackageName())); } else if (source instanceof FileSource) { FileSource fileSource = (FileSource) source; sources.append(fileSource(fileSource.getFile()), // element -> fileSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } else if (source instanceof DirectorySource) { sources.append(directorySource(((DirectorySource) source).getFile())); } else if (source instanceof UriSource) { sources.append(uriSource(((UriSource) source).getUri())); } } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { String id = inProgressIds.get(testIdentifier.getUniqueIdObject()); eventsFileWriter.append(reported(id, Instant.now()), // reported -> reported.append(attachments(), attachments -> attachments.append(data(), data -> { data.withTime(entry.getTimestamp()); entry.getKeyValuePairs().forEach(data::addEntry); }))); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { String id = inProgressIds.remove(testIdentifier.getUniqueIdObject()); eventsFileWriter.append(finished(id, Instant.now()), // finished -> finished.append(result(convertStatus(testExecutionResult.getStatus())), // result -> testExecutionResult.getThrowable() // .ifPresent(throwable -> result.append(throwable(throwable))))); } private Result.Status convertStatus(TestExecutionResult.Status status) { switch (status) { case FAILED: return Result.Status.FAILED; case SUCCESSFUL: return Result.Status.SUCCESSFUL; case ABORTED: return Result.Status.ABORTED; } throw new JUnitException("Unhandled status: " + status); } } Type.java000066400000000000000000000015651455764576500336770ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import org.junit.platform.engine.TestDescriptor; import org.opentest4j.reporting.events.api.ChildElement; import org.opentest4j.reporting.events.api.Context; import org.opentest4j.reporting.events.core.Metadata; import org.opentest4j.reporting.schema.QualifiedName; class Type extends ChildElement { static final QualifiedName ELEMENT = QualifiedName.of(JUnitFactory.NAMESPACE, "type"); Type(Context context, TestDescriptor.Type type) { super(context, ELEMENT); withContent(type.toString()); } } UniqueId.java000066400000000000000000000014761455764576500345020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import org.opentest4j.reporting.events.api.ChildElement; import org.opentest4j.reporting.events.api.Context; import org.opentest4j.reporting.events.core.Metadata; import org.opentest4j.reporting.schema.QualifiedName; class UniqueId extends ChildElement { static final QualifiedName ELEMENT = QualifiedName.of(JUnitFactory.NAMESPACE, "uniqueId"); UniqueId(Context context, String value) { super(context, ELEMENT); withContent(value); } } package-info.java000066400000000000000000000002041455764576500352670ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/** * Support for generating Open Test Reporting compatible XML event reports. */ package org.junit.platform.reporting.open.xml; junit5-r5.10.2/junit-platform-reporting/src/main/java/org/junit/platform/reporting/package-info.java000066400000000000000000000001141455764576500336050ustar00rootroot00000000000000/** * JUnit Platform Reporting. */ package org.junit.platform.reporting; junit5-r5.10.2/junit-platform-reporting/src/main/resources/000077500000000000000000000000001455764576500237365ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/META-INF/000077500000000000000000000000001455764576500250765ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500267215ustar00rootroot00000000000000org.junit.platform.launcher.TestExecutionListener000066400000000000000000000001071455764576500404350ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/META-INF/servicesorg.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/000077500000000000000000000000001455764576500245255ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/000077500000000000000000000000001455764576500256565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/000077500000000000000000000000001455764576500275025ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/reporting/000077500000000000000000000000001455764576500315135ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/reporting/open/000077500000000000000000000000001455764576500324545ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/reporting/open/xml/000077500000000000000000000000001455764576500332545ustar00rootroot00000000000000catalog.xml000066400000000000000000000003131455764576500353260ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/reporting/open/xml junit.xsd000066400000000000000000000017251455764576500350530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/main/resources/org/junit/platform/reporting/open/xml junit5-r5.10.2/junit-platform-reporting/src/module/000077500000000000000000000000001455764576500222655ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/module/org.junit.platform.reporting/000077500000000000000000000000001455764576500300375ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-reporting/src/module/org.junit.platform.reporting/module-info.java000066400000000000000000000017141455764576500331230ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Defines the JUnit Platform Reporting API. * * @since 1.4 */ module org.junit.platform.reporting { requires java.xml; requires static transitive org.apiguardian.api; requires org.junit.platform.commons; requires transitive org.junit.platform.engine; requires transitive org.junit.platform.launcher; // exports org.junit.platform.reporting; empty package exports org.junit.platform.reporting.legacy; exports org.junit.platform.reporting.legacy.xml; exports org.junit.platform.reporting.open.xml; provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener; } junit5-r5.10.2/junit-platform-runner/000077500000000000000000000000001455764576500175115ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/junit-platform-runner.gradle.kts000066400000000000000000000016101455764576500257510ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") id("junitbuild.junit4-compatibility") } description = "JUnit Platform Runner" dependencies { api(platform(projects.junitBom)) api(libs.junit4) api(projects.junitPlatformLauncher) api(projects.junitPlatformSuiteApi) compileOnlyApi(libs.apiguardian) implementation(projects.junitPlatformSuiteCommons) testImplementation(testFixtures(projects.junitPlatformEngine)) testImplementation(testFixtures(projects.junitPlatformLauncher)) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } tasks.jar { bundle { val importAPIGuardian: String by extra bnd(""" # Import JUnit4 packages with a version Import-Package: \ $importAPIGuardian,\ org.junit.platform.commons.logging;status=INTERNAL,\ org.junit.runner.*;version="[${libs.versions.junit4Min.get()},5)",\ * """) } } junit5-r5.10.2/junit-platform-runner/src/000077500000000000000000000000001455764576500203005ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/000077500000000000000000000000001455764576500212245ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/000077500000000000000000000000001455764576500221455ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/000077500000000000000000000000001455764576500227345ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/000077500000000000000000000000001455764576500240655ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500257115ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/runner/000077500000000000000000000000001455764576500272225ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatform.java000066400000000000000000000166041455764576500326320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.runner; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder.request; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.List; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.ExcludeClassNamePatterns; import org.junit.platform.suite.api.ExcludeEngines; import org.junit.platform.suite.api.ExcludePackages; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.IncludePackages; import org.junit.platform.suite.api.IncludeTags; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.SelectDirectories; import org.junit.platform.suite.api.SelectFile; import org.junit.platform.suite.api.SelectModules; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.SelectUris; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder; import org.junit.runner.Description; import org.junit.runner.Runner; import org.junit.runner.manipulation.Filter; import org.junit.runner.manipulation.Filterable; import org.junit.runner.manipulation.NoTestsRemainException; import org.junit.runner.notification.RunNotifier; /** * JUnit 4 based {@link Runner} which runs tests on the JUnit Platform in a * JUnit 4 environment. * *

Annotating a class with {@code @RunWith(JUnitPlatform.class)} allows it * to be run with IDEs and build systems that support JUnit 4 but do not yet * support the JUnit Platform directly. * *

Please note that test classes and suites annotated with * {@code @RunWith(JUnitPlatform.class)} cannot be executed directly on * the JUnit Platform (or as a "JUnit 5" test as documented in some IDEs). Such * classes and suites can only be executed using JUnit 4 infrastructure. * *

Consult the various annotations in the {@code org.junit.platform.suite.api} * package for configuration options. * *

If you do not use any configuration annotations from the * {@code org.junit.platform.suite.api} package, you can use this runner on a * test class whose programming model is supported on the JUnit Platform — * for example, a JUnit Jupiter test class. Note, however, that any test class * run with this runner must be {@code public} in order to be picked up by IDEs * and build tools. * *

When used on a class that serves as a test suite and the * {@link IncludeClassNamePatterns @IncludeClassNamePatterns} annotation is not * present, the default include pattern * {@value org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN} * will be used in order to avoid loading classes unnecessarily (see {@link * org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN * ClassNameFilter#STANDARD_INCLUDE_PATTERN}). * * @since 1.0 * @see SelectClasses * @see SelectClasspathResource * @see SelectDirectories * @see SelectFile * @see SelectModules * @see SelectPackages * @see SelectUris * @see IncludeClassNamePatterns * @see ExcludeClassNamePatterns * @see IncludeEngines * @see ExcludeEngines * @see IncludePackages * @see ExcludePackages * @see IncludeTags * @see ExcludeTags * @see SuiteDisplayName * @see org.junit.platform.suite.api.UseTechnicalNames UseTechnicalNames * @see ConfigurationParameter * @deprecated since 1.8, in favor of the {@link Suite @Suite} support provided by * the {@code junit-platform-suite-engine} module; to be removed in JUnit Platform 2.0 */ @API(status = DEPRECATED, since = "1.8") @Deprecated public class JUnitPlatform extends Runner implements Filterable { // @formatter:off private static final List> IMPLICIT_SUITE_ANNOTATIONS = Arrays.asList( SelectClasses.class, SelectClasspathResource.class, SelectDirectories.class, SelectFile.class, SelectFile.class, SelectModules.class, SelectPackages.class, SelectUris.class ); // @formatter:on private final Class testClass; private final Launcher launcher; private JUnitPlatformTestTree testTree; public JUnitPlatform(Class testClass) { this(testClass, LauncherFactory.create()); } // For testing only JUnitPlatform(Class testClass, Launcher launcher) { this.launcher = launcher; this.testClass = testClass; this.testTree = generateTestTree(createDiscoveryRequest()); } @Override public Description getDescription() { return this.testTree.getSuiteDescription(); } @Override public void run(RunNotifier notifier) { this.launcher.execute(this.testTree.getTestPlan(), new JUnitPlatformRunnerListener(this.testTree, notifier)); } private JUnitPlatformTestTree generateTestTree(LauncherDiscoveryRequest discoveryRequest) { TestPlan testPlan = this.launcher.discover(discoveryRequest); return new JUnitPlatformTestTree(testPlan, this.testClass); } private LauncherDiscoveryRequest createDiscoveryRequest() { SuiteLauncherDiscoveryRequestBuilder requestBuilder = request(); // Allows @RunWith(JUnitPlatform.class) to be added to any test case boolean isSuite = isSuite(); if (!isSuite) { requestBuilder.selectors(selectClass(this.testClass)); } // @formatter:off return requestBuilder .filterStandardClassNamePatterns(isSuite) .suite(this.testClass) .build(); // @formatter:on } private boolean isSuite() { // @formatter:off return IMPLICIT_SUITE_ANNOTATIONS.stream() .anyMatch(annotation -> isAnnotated(this.testClass, annotation)); // @formatter:on } @Override public void filter(Filter filter) throws NoTestsRemainException { Set filteredIdentifiers = this.testTree.getFilteredLeaves(filter); if (filteredIdentifiers.isEmpty()) { throw new NoTestsRemainException(); } this.testTree = generateTestTree(createDiscoveryRequestForUniqueIds(filteredIdentifiers)); } private LauncherDiscoveryRequest createDiscoveryRequestForUniqueIds(Set testIdentifiers) { // @formatter:off List selectors = testIdentifiers.stream() .map(TestIdentifier::getUniqueIdObject) .map(DiscoverySelectors::selectUniqueId) .collect(toList()); // @formatter:on return request().selectors(selectors).build(); } } JUnitPlatformRunnerListener.java000066400000000000000000000061261455764576500354510ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/runner/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.runner; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; /** * @since 1.0 */ class JUnitPlatformRunnerListener implements TestExecutionListener { private final JUnitPlatformTestTree testTree; private final RunNotifier notifier; JUnitPlatformRunnerListener(JUnitPlatformTestTree testTree, RunNotifier notifier) { this.testTree = testTree; this.notifier = notifier; } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { UniqueId parentId = testIdentifier.getParentIdObject().get(); testTree.addDynamicDescription(testIdentifier, parentId); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { if (testIdentifier.isTest()) { fireTestIgnored(testIdentifier); } else { testTree.getTestsInSubtree(testIdentifier).forEach(this::fireTestIgnored); } } private void fireTestIgnored(TestIdentifier testIdentifier) { Description description = findJUnit4Description(testIdentifier); this.notifier.fireTestIgnored(description); } @Override public void executionStarted(TestIdentifier testIdentifier) { Description description = findJUnit4Description(testIdentifier); if (description.isTest()) { this.notifier.fireTestStarted(description); } } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { Description description = findJUnit4Description(testIdentifier); Status status = testExecutionResult.getStatus(); if (status == ABORTED) { this.notifier.fireTestAssumptionFailed(toFailure(testExecutionResult, description)); } else if (status == FAILED) { this.notifier.fireTestFailure(toFailure(testExecutionResult, description)); } if (description.isTest()) { this.notifier.fireTestFinished(description); } } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { System.out.println(entry); } private Failure toFailure(TestExecutionResult testExecutionResult, Description description) { return new Failure(description, testExecutionResult.getThrowable().orElse(null)); } private Description findJUnit4Description(TestIdentifier testIdentifier) { return this.testTree.getDescription(testIdentifier); } } JUnitPlatformTestTree.java000066400000000000000000000136511455764576500342320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/runner/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.runner; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; /** * @since 1.0 */ class JUnitPlatformTestTree { private final Map descriptions = new HashMap<>(); private final TestPlan testPlan; private final Function nameExtractor; private final Description suiteDescription; JUnitPlatformTestTree(TestPlan testPlan, Class testClass) { this.testPlan = testPlan; this.nameExtractor = useTechnicalNames(testClass) ? this::getTechnicalName : TestIdentifier::getDisplayName; this.suiteDescription = generateSuiteDescription(testPlan, testClass); } public TestPlan getTestPlan() { return testPlan; } @SuppressWarnings("deprecation") private static boolean useTechnicalNames(Class testClass) { return testClass.isAnnotationPresent(org.junit.platform.suite.api.UseTechnicalNames.class); } Description getSuiteDescription() { return this.suiteDescription; } Description getDescription(TestIdentifier identifier) { return this.descriptions.get(identifier); } private Description generateSuiteDescription(TestPlan testPlan, Class testClass) { String displayName = useTechnicalNames(testClass) ? testClass.getName() : getSuiteDisplayName(testClass); Description suiteDescription = Description.createSuiteDescription(displayName); buildDescriptionTree(suiteDescription, testPlan); return suiteDescription; } private String getSuiteDisplayName(Class testClass) { // @formatter:off return AnnotationUtils.findAnnotation(testClass, SuiteDisplayName.class) .map(SuiteDisplayName::value) .filter(StringUtils::isNotBlank) .orElse(testClass.getName()); // @formatter:on } private void buildDescriptionTree(Description suiteDescription, TestPlan testPlan) { testPlan.getRoots().forEach(testIdentifier -> buildDescription(testIdentifier, suiteDescription, testPlan)); } void addDynamicDescription(TestIdentifier newIdentifier, UniqueId parentId) { Description parent = getDescription(this.testPlan.getTestIdentifier(parentId)); buildDescription(newIdentifier, parent, this.testPlan); } private void buildDescription(TestIdentifier identifier, Description parent, TestPlan testPlan) { Description newDescription = createJUnit4Description(identifier, testPlan); parent.addChild(newDescription); this.descriptions.put(identifier, newDescription); testPlan.getChildren(identifier).forEach( testIdentifier -> buildDescription(testIdentifier, newDescription, testPlan)); } private Description createJUnit4Description(TestIdentifier identifier, TestPlan testPlan) { String name = nameExtractor.apply(identifier); if (identifier.isTest()) { String containerName = testPlan.getParent(identifier).map(nameExtractor).orElse(""); return Description.createTestDescription(containerName, name, identifier.getUniqueIdObject()); } return Description.createSuiteDescription(name, identifier.getUniqueIdObject()); } private String getTechnicalName(TestIdentifier testIdentifier) { Optional optionalSource = testIdentifier.getSource(); if (optionalSource.isPresent()) { TestSource source = optionalSource.get(); if (source instanceof ClassSource) { return ((ClassSource) source).getJavaClass().getName(); } else if (source instanceof MethodSource) { MethodSource methodSource = (MethodSource) source; String methodParameterTypes = methodSource.getMethodParameterTypes(); if (StringUtils.isBlank(methodParameterTypes)) { return methodSource.getMethodName(); } return String.format("%s(%s)", methodSource.getMethodName(), methodParameterTypes); } } // Else fall back to display name return testIdentifier.getDisplayName(); } Set getTestsInSubtree(TestIdentifier ancestor) { // @formatter:off return testPlan.getDescendants(ancestor).stream() .filter(TestIdentifier::isTest) .collect(toCollection(LinkedHashSet::new)); // @formatter:on } Set getFilteredLeaves(Filter filter) { Set identifiers = applyFilterToDescriptions(filter); return removeNonLeafIdentifiers(identifiers); } private Set removeNonLeafIdentifiers(Set identifiers) { return identifiers.stream().filter(isALeaf(identifiers)).collect(toSet()); } private Predicate isALeaf(Set identifiers) { return testIdentifier -> { Set descendants = testPlan.getDescendants(testIdentifier); return identifiers.stream().noneMatch(descendants::contains); }; } private Set applyFilterToDescriptions(Filter filter) { // @formatter:off return descriptions.entrySet() .stream() .filter(entry -> filter.shouldRun(entry.getValue())) .map(Entry::getKey) .collect(toSet()); // @formatter:on } } junit5-r5.10.2/junit-platform-runner/src/main/java/org/junit/platform/runner/package-info.java000066400000000000000000000002451455764576500324120ustar00rootroot00000000000000/** * {@code Runner} and annotations for configuring and executing tests on the * JUnit Platform in a JUnit 4 environment. */ package org.junit.platform.runner; junit5-r5.10.2/junit-platform-runner/src/module/000077500000000000000000000000001455764576500215655ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/module/org.junit.platform.runner/000077500000000000000000000000001455764576500266375ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-runner/src/module/org.junit.platform.runner/module-info.java000066400000000000000000000013721455764576500317230ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * {@code Runner} and annotations for configuring and executing tests on the * JUnit Platform in a JUnit 4 environment. * * @since 1.0 */ module org.junit.platform.runner { requires transitive junit; // 4 requires static transitive org.apiguardian.api; requires transitive org.junit.platform.launcher; requires transitive org.junit.platform.suite.api; requires org.junit.platform.suite.commons; exports org.junit.platform.runner; } junit5-r5.10.2/junit-platform-suite-api/000077500000000000000000000000001455764576500201005ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/junit-platform-suite-api.gradle.kts000066400000000000000000000004761455764576500267400ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite API" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-suite-api/src/000077500000000000000000000000001455764576500206675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/000077500000000000000000000000001455764576500216135ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/000077500000000000000000000000001455764576500225345ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/000077500000000000000000000000001455764576500233235ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/000077500000000000000000000000001455764576500244545ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500263005ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/000077500000000000000000000000001455764576500274315ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/000077500000000000000000000000001455764576500302025ustar00rootroot00000000000000ConfigurationParameter.java000066400000000000000000000032641455764576500354430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ConfigurationParameter} is a {@linkplain Repeatable repeatable} * annotation that specifies a configuration {@link #key key} and * {@link #value value} pair to be added to the discovery request when running * a test suite on the JUnit Platform. * * @since 1.8 * @see DisableParentConfigurationParameters * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder#configurationParameter(String, String) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") @Repeatable(ConfigurationParameters.class) public @interface ConfigurationParameter { /** * The configuration parameter key under which to add the {@link #value() value} * to the discovery request; never {@code null} or blank. */ String key(); /** * The value to add to the discovery request for the specified {@link #key() key}. */ String value(); } ConfigurationParameters.java000066400000000000000000000026101455764576500356200ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ConfigurationParameters} is a container for one or more * {@link ConfigurationParameter @ConfigurationParameter} declarations. * *

Note, however, that use of the {@code @ConfigurationParameters} container * is completely optional since {@code @ConfigurationParameter} is a * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. * * @since 1.8 * @see ConfigurationParameter */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface ConfigurationParameters { /** * An array of one or more {@link ConfigurationParameter @ConfigurationParameter} * declarations. */ ConfigurationParameter[] value(); } DisableParentConfigurationParameters.java000066400000000000000000000025621455764576500402640ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * Disable parent configuration parameters. * *

By default a suite discovers tests using the configuration parameters * explicitly configured via {@link ConfigurationParameter @ConfigurationParameter} * and the configuration parameters from the discovery request that was used to * discover the suite. * *

Annotating a suite with this annotation disables the latter source so * that only explicit configuration parameters are taken into account. * * @since 1.8 * @see ConfigurationParameter * @see Suite */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface DisableParentConfigurationParameters { } ExcludeClassNamePatterns.java000066400000000000000000000027471455764576500357010ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ExcludeClassNamePatterns} specifies regular expressions that are used * to match against fully qualified class names when running a test suite on the * JUnit Platform. * *

The patterns are combined using OR semantics: if the fully qualified name * of a class matches against at least one of the patterns, the class will be * excluded from the test plan. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.ClassNameFilter#excludeClassNamePatterns */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface ExcludeClassNamePatterns { /** * Regular expressions used to match against fully qualified class names. */ String[] value(); } ExcludeEngines.java000066400000000000000000000024141455764576500336710ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ExcludeEngines} specifies the {@linkplain #value IDs} of * {@link org.junit.platform.engine.TestEngine TestEngines} to be excluded * when running a test suite on the JUnit Platform. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.EngineFilter#excludeEngines */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface ExcludeEngines { /** * One or more TestEngine IDs to be excluded from the test plan. */ String[] value(); } ExcludePackages.java000066400000000000000000000023221455764576500340150ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ExcludePackages} specifies the {@linkplain #value packages} to be * excluded when running a test suite on the JUnit Platform. * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.PackageNameFilter#excludePackageNames(String...) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface ExcludePackages { /** * One or more packages to exclude. */ String[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java000066400000000000000000000044451455764576500332640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @ExcludeTags} specifies the * {@linkplain #value tags or tag expressions} to be excluded when running a * test suite on the JUnit Platform. * *

Tag Expressions

* *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and) and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the * JUnit 5 User Guide * for usage examples. * *

Syntax Rules for Tags

*
    *
  • A tag must not be blank.
  • *
  • A trimmed tag must not contain whitespace.
  • *
  • A trimmed tag must not contain ISO control characters.
  • *
  • A trimmed tag must not contain reserved characters.
  • *
* *

Reserved characters that are not permissible as part of a tag name. * *

    *
  • {@code ","}
  • *
  • {@code "("}
  • *
  • {@code ")"}
  • *
  • {@code "&"}
  • *
  • {@code "|"}
  • *
  • {@code "!"}
  • *
* * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.TagFilter#excludeTags */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface ExcludeTags { /** * One or more tags to exclude. * *

Note: each tag will be {@linkplain String#trim() trimmed} and * validated according to the Syntax Rules for Tags (see * {@linkplain ExcludeTags class-level Javadoc} for details). */ String[] value(); } IncludeClassNamePatterns.java000066400000000000000000000037631455764576500356720ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @IncludeClassNamePatterns} specifies regular expressions that are used * to match against fully qualified class names when running a test suite on the * JUnit Platform. * *

The patterns are combined using OR semantics: if the fully qualified name * of a class matches against at least one of the patterns, the class will be * included in the test plan. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN * @see org.junit.platform.engine.discovery.ClassNameFilter#includeClassNamePatterns */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface IncludeClassNamePatterns { /** * Regular expressions used to match against fully qualified class names. * *

The default pattern matches against classes whose names either begin * with {@code Test} or end with {@code Test} or {@code Tests} (in any package). */ // Implementation notes: // - Test.* :: "Test" prefix for classes in default package // - .+[.$]Test.* :: "Test" prefix for top-level and nested classes in a named package // - .*Tests? :: "Test" and "Tests" suffixes in any package String[] value() default "^(Test.*|.+[.$]Test.*|.*Tests?)$"; } IncludeEngines.java000066400000000000000000000024121455764576500336610ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @IncludeEngines} specifies the {@linkplain #value IDs} of * {@link org.junit.platform.engine.TestEngine TestEngines} to be included * when running a test suite on the JUnit Platform. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.EngineFilter#includeEngines */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface IncludeEngines { /** * One or more TestEngine IDs to be included in the test plan. */ String[] value(); } IncludePackages.java000066400000000000000000000023241455764576500340110ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @IncludePackages} specifies the {@linkplain #value packages} to be * included when running a test suite on the JUnit Platform. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.PackageNameFilter#includePackageNames(String...) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface IncludePackages { /** * One or more packages to include. */ String[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java000066400000000000000000000044451455764576500332560ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @IncludeTags} specifies the * {@linkplain #value tags or tag expressions} to be included when running a * test suite on the JUnit Platform. * *

Tag Expressions

* *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and) and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the * JUnit 5 User Guide * for usage examples. * *

Syntax Rules for Tags

*
    *
  • A tag must not be blank.
  • *
  • A trimmed tag must not contain whitespace.
  • *
  • A trimmed tag must not contain ISO control characters.
  • *
  • A trimmed tag must not contain reserved characters.
  • *
* *

Reserved characters that are not permissible as part of a tag name. * *

    *
  • {@code ","}
  • *
  • {@code "("}
  • *
  • {@code ")"}
  • *
  • {@code "&"}
  • *
  • {@code "|"}
  • *
  • {@code "!"}
  • *
* * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.TagFilter#includeTags */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface IncludeTags { /** * One or more tags to include. * *

Note: each tag will be {@linkplain String#trim() trimmed} and * validated according to the Syntax Rules for Tags (see * {@linkplain IncludeTags class-level Javadoc} for details). */ String[] value(); } SelectClasses.java000066400000000000000000000035721455764576500335320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectClasses} specifies the classes to select when running * a test suite on the JUnit Platform. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClass(Class) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClass(String) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface SelectClasses { /** * One or more classes to select. * *

May be use in conjunction with or instead of {@link #names() names}. */ Class[] value() default {}; /** * One or more classes to select by their fully qualified names. * *

May be use in conjunction with or instead of {@link #value() value}. * *

This attribute is intended to be used when a class cannot be referenced * directly from where this annotation is used — for example, when a * class is not visible due to being private or package-private. * * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") String[] names() default {}; } SelectClasspathResource.java000066400000000000000000000032761455764576500355700ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectClasspathResource} is a {@linkplain Repeatable repeatable} * annotation that specifies a classpath resource to select when running * a test suite on the JUnit Platform. * * @since 1.8 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClasspathResource(String, org.junit.platform.engine.discovery.FilePosition) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") @Repeatable(SelectClasspathResources.class) public @interface SelectClasspathResource { /** * The name of the classpath resource to select. */ String value(); /** * The line number within the classpath resource; ignored if not greater than * zero. */ int line() default 0; /** * The column number within the classpath resource; ignored if the line number * is ignored or if not greater than zero. */ int column() default 0; } SelectClasspathResources.java000066400000000000000000000026231455764576500357460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectClasspathResources} is a container for one or more * {@link SelectClasspathResource @SelectClasspathResource} declarations. * *

Note, however, that use of the {@code @SelectClasspathResources} container is * completely optional since {@code @SelectClasspathResource} is a * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. * * @since 1.8 * @see SelectClasspathResource */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface SelectClasspathResources { /** * An array of one or more {@link SelectClasspathResource @SelectClasspathResource} * declarations. */ SelectClasspathResource[] value(); } SelectDirectories.java000066400000000000000000000023001455764576500343750ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectDirectories} specifies the directories to select when * running a test suite on the JUnit Platform. * * @since 1.8 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectDirectory(String) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface SelectDirectories { /** * One or more directories to select. */ String[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFile.java000066400000000000000000000031021455764576500330600ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectFile} is a {@linkplain Repeatable repeatable} annotation that * specifies a file to select when running a test suite on the JUnit * Platform. * * @since 1.8 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectFile(String, org.junit.platform.engine.discovery.FilePosition) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") @Repeatable(SelectFiles.class) public @interface SelectFile { /** * The file to select. */ String value(); /** * The line number within the file; ignored if not greater than zero. */ int line() default 0; /** * The column number within the file; ignored if the line number is ignored * or if not greater than zero. */ int column() default 0; } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFiles.java000066400000000000000000000024151455764576500332510ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectFiles} is a container for one or more * {@link SelectFile @SelectFile} declarations. * *

Note, however, that use of the {@code @SelectFiles} container is * completely optional since {@code @SelectFile} is a * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. * * @since 1.8 * @see SelectFile */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface SelectFiles { /** * An array of one or more {@link SelectFile @SelectFile} declarations. */ SelectFile[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethod.java000066400000000000000000000151321455764576500334270ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectMethod} is a {@linkplain Repeatable repeatable} annotation that * specifies a method to select when running a test suite on the JUnit * Platform. * * @since 1.10 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String, String, String) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String, String, Class...) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(Class, String, String) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(Class, String, Class...) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = EXPERIMENTAL, since = "1.10") @Repeatable(SelectMethods.class) public @interface SelectMethod { /** * The fully qualified method name of the method to select. * *

The following formats are supported. * *

    *
  • {@code [fully qualified class name]#[methodName]}
  • *
  • {@code [fully qualified class name]#[methodName](parameter type list)} *
* *

The parameter type list is a comma-separated list of primitive * names or fully qualified class names for the types of parameters accepted * by the method. * *

Array parameter types may be specified using either the JVM's internal * String representation (e.g., {@code [[I} for {@code int[][]}, * {@code [Ljava.lang.String;} for {@code java.lang.String[]}, etc.) or * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, * etc.). * * * * * * * * * * * * * * * * *
Examples
MethodFully Qualified Method Name
{@code java.lang.String.chars()}{@code java.lang.String#chars}
{@code java.lang.String.chars()}{@code java.lang.String#chars()}
{@code java.lang.String.equalsIgnoreCase(String)}{@code java.lang.String#equalsIgnoreCase(java.lang.String)}
{@code java.lang.String.substring(int, int)}{@code java.lang.String#substring(int, int)}
{@code example.Calc.avg(int[])}{@code example.Calc#avg([I)}
{@code example.Calc.avg(int[])}{@code example.Calc#avg(int[])}
{@code example.Matrix.multiply(double[][])}{@code example.Matrix#multiply([[D)}
{@code example.Matrix.multiply(double[][])}{@code example.Matrix#multiply(double[][])}
{@code example.Service.process(String[])}{@code example.Service#process([Ljava.lang.String;)}
{@code example.Service.process(String[])}{@code example.Service#process(java.lang.String[])}
{@code example.Service.process(String[][])}{@code example.Service#process([[Ljava.lang.String;)}
{@code example.Service.process(String[][])}{@code example.Service#process(java.lang.String[][])}
* *

Cannot be combined with any other attribute. * * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String) */ String value() default ""; /** * The class in which the method is declared, or a subclass thereof. * *

Cannot be used in conjunction with {@link #typeName()}. */ Class type() default Class.class; /** * The fully qualified class name in which the method is declared, or a subclass thereof. * *

Cannot be used in conjunction with {@link #type()}. */ String typeName() default ""; /** * The name of the method to select; never blank unless {@link #value()} is used. */ String name() default ""; /** * The parameter types of the method to select. * *

Cannot be used in conjunction with {@link #parameterTypeNames()}. */ Class[] parameterTypes() default {}; /** * The parameter types of the method to select. * *

This is typically a comma-separated list of atomic types, fully * qualified class names, or array types; however, the exact syntax * depends on the underlying test engine. * *

If the method takes no parameters, this attribute must be an * empty string. * *

Array parameter types may be specified using either the JVM's internal * String representation (e.g., {@code [[I} for {@code int[][]}, * {@code [Ljava.lang.String;} for {@code java.lang.String[]}, etc.) or * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, * etc.). * * * * * * * * * * * * * * * *
Examples
MethodParameter types list
{@code java.lang.String.chars()}The empty string
{@code java.lang.String.equalsIgnoreCase(String)}{@code java.lang.String}
{@code java.lang.String.substring(int, int)}{@code int, int}
{@code example.Calc.avg(int[])}{@code [I}
{@code example.Calc.avg(int[])}{@code int[]}
{@code example.Matrix.multiply(double[][])}{@code [[D}
{@code example.Matrix.multiply(double[][])}{@code double[][]}
{@code example.Service.process(String[])}{@code [Ljava.lang.String;}
{@code example.Service.process(String[])}{@code java.lang.String[]}
{@code example.Service.process(String[][])}{@code [[Ljava.lang.String;}
{@code example.Service.process(String[][])}{@code java.lang.String[][]}
* *

Cannot be used in conjunction with {@link #parameterTypes()}. */ String parameterTypeNames() default ""; } SelectMethods.java000066400000000000000000000024561455764576500335400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectMethods} is a container for one or more * {@link SelectMethod @SelectMethod} declarations. * *

Note, however, that use of the {@code @SelectMethods} container is * completely optional since {@code @SelectMethod} is a * {@linkplain java.lang.annotation.Repeatable repeatable} annotation. * * @since 1.10 * @see SelectMethod */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = EXPERIMENTAL, since = "1.10") public @interface SelectMethods { /** * An array of one or more {@link SelectMethod @SelectMethod} declarations. */ SelectMethod[] value(); } SelectModules.java000066400000000000000000000023011455764576500335320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Set; import org.apiguardian.api.API; /** * {@code @SelectModules} specifies the modules to select when running * a test suite on the JUnit Platform. * * @since 1.8 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface SelectModules { /** * One or more modules to select. */ String[] value(); } SelectPackages.java000066400000000000000000000023271455764576500336500ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectPackages} specifies the names of packages to select * when running a test suite on the JUnit Platform. * * @since 1.0 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectPackage(String) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = MAINTAINED, since = "1.0") public @interface SelectPackages { /** * One or more fully qualified package names to select. */ String[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectUris.java000066400000000000000000000022361455764576500331320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SelectUris} specifies the URIs to select when running a test * suite on the JUnit Platform. * * @since 1.8 * @see Suite * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectUri(String) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") public @interface SelectUris { /** * One or more URIs to select. */ String[] value(); } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Suite.java000066400000000000000000000056061455764576500321450ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.junit.platform.commons.annotation.Testable; /** * {@code @Suite} marks a class as a test suite on the JUnit Platform. * *

Selector and filter annotations are used to control the contents of the * suite. Additionally configuration can be passed to the suite via the * configuration annotations. * *

When the {@link IncludeClassNamePatterns @IncludeClassNamePatterns} * annotation is not present, the default include pattern * {@value org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN} * will be used in order to avoid loading classes unnecessarily (see {@link * org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN * ClassNameFilter#STANDARD_INCLUDE_PATTERN}). * *

By default a suite discovers tests using the configuration parameters * explicitly configured by {@link ConfigurationParameter @ConfigurationParameter} * and the configuration parameters from the discovery request that discovered * the suite. Annotating a suite with * {@link DisableParentConfigurationParameters @DisableParentConfigurationParameters} * annotation disables the latter as a source of parameters so that only explicit * configuration parameters are taken into account. * * @since 1.8 * @see SelectClasses * @see SelectClasspathResource * @see SelectDirectories * @see SelectFile * @see SelectModules * @see SelectPackages * @see SelectUris * @see IncludeClassNamePatterns * @see ExcludeClassNamePatterns * @see IncludeEngines * @see ExcludeEngines * @see IncludePackages * @see ExcludePackages * @see IncludeTags * @see ExcludeTags * @see SuiteDisplayName * @see ConfigurationParameter * @see DisableParentConfigurationParameters * @see org.junit.platform.launcher.LauncherDiscoveryRequest * @see org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder * @see org.junit.platform.launcher.Launcher */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = STABLE, since = "1.10") @Testable public @interface Suite { /** * Fail suite if no tests were discovered. * * @since 1.9 */ @API(status = Status.EXPERIMENTAL, since = "1.9") boolean failIfNoTests() default true; } SuiteDisplayName.java000066400000000000000000000032571455764576500342150ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @SuiteDisplayName} is used to declare a {@linkplain #value custom * display name} for the annotated test class that is executed as a test suite * on the JUnit Platform. * *

Display names are typically used for test reporting in IDEs and build * tools and may contain spaces, special characters, and even emoji. * *

JUnit 4 Suite Support

*

Test suites can be run on the JUnit Platform in a JUnit 4 environment via * {@code @RunWith(JUnitPlatform.class)}. * *

JUnit 5 Suite Support

*

Test suites can be run on the JUnit Platform in a JUnit 5 environment via * the {@code junit-platform-suite-engine} module. * * @since 1.1 * @see Suite * @see org.junit.platform.runner.JUnitPlatform */ @Retention(RUNTIME) @Target(TYPE) @Documented @API(status = MAINTAINED, since = "1.1") public @interface SuiteDisplayName { /** * Custom display name for the annotated class. * * @return a custom display name; never blank or consisting solely of * whitespace */ String value(); } UseTechnicalNames.java000066400000000000000000000041231455764576500343210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.api; import static org.apiguardian.api.API.Status.DEPRECATED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.apiguardian.api.API; /** * {@code @UseTechnicalNames} specifies that technical names should be * used instead of display names when running a test suite on the * JUnit Platform. * *

By default, display names will be used for test artifacts in * reports and graphical displays in IDEs; however, when a JUnit Platform test * suite is executed with a build tool such as Gradle or Maven, the generated * test report may need to include the technical names of test * artifacts — for example, fully qualified class names — instead * of shorter display names like the simple name of a test class or a * custom display name containing special characters. * *

Note that the presence of {@code @UseTechnicalNames} overrides any custom * display name configured for the suite via {@link SuiteDisplayName @SuiteDisplayName}. * *

JUnit 4 Suite Support

*

Test suites can be run on the JUnit Platform in a JUnit 4 environment via * {@code @RunWith(JUnitPlatform.class)}. * * @since 1.0 * @see org.junit.platform.runner.JUnitPlatform * @deprecated since 1.8, in favor of the {@link Suite @Suite} support provided by * the {@code junit-platform-suite-engine} module; to be removed in JUnit Platform 2.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @Documented @API(status = DEPRECATED, since = "1.8") @Deprecated public @interface UseTechnicalNames { } junit5-r5.10.2/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java000066400000000000000000000007741455764576500334010ustar00rootroot00000000000000/** * Annotations for configuring a test suite on the JUnit Platform. * *

JUnit 4 Suite Support

*

Test suites can be run on the JUnit Platform in a JUnit 4 environment via * {@code @RunWith(JUnitPlatform.class)} with the {@code junit-platform-runner}. * *

JUnit 5 Suite Support

*

Test suites can be run on the JUnit Platform in a JUnit 5 environment via * {@link Suite @Suite} with the {@code junit-platform-suite-engine}. */ package org.junit.platform.suite.api; junit5-r5.10.2/junit-platform-suite-api/src/module/000077500000000000000000000000001455764576500221545ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/module/org.junit.platform.suite.api/000077500000000000000000000000001455764576500276165ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-api/src/module/org.junit.platform.suite.api/module-info.java000066400000000000000000000011111455764576500326710ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Annotations for configuring a test suite on the JUnit Platform. * * @since 1.0 */ module org.junit.platform.suite.api { requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; exports org.junit.platform.suite.api; } junit5-r5.10.2/junit-platform-suite-commons/000077500000000000000000000000001455764576500210025ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts000066400000000000000000000006421455764576500305370ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite Commons" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) implementation(projects.junitPlatformEngine) implementation(projects.junitPlatformSuiteApi) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-suite-commons/src/000077500000000000000000000000001455764576500215715ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/000077500000000000000000000000001455764576500225155ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/000077500000000000000000000000001455764576500234365ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/000077500000000000000000000000001455764576500242255ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/000077500000000000000000000000001455764576500253565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500272025ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/000077500000000000000000000000001455764576500303335ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/000077500000000000000000000000001455764576500320065ustar00rootroot00000000000000AdditionalDiscoverySelectors.java000066400000000000000000000104551455764576500404230ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.commons; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.FilePosition; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; /** * @since 1.8 */ class AdditionalDiscoverySelectors { static List selectUris(String... uris) { Preconditions.notNull(uris, "URI list must not be null"); Preconditions.containsNoNullElements(uris, "Individual URIs must not be null"); // @formatter:off return uniqueStreamOf(uris) .filter(StringUtils::isNotBlank) .map(DiscoverySelectors::selectUri) .collect(Collectors.toList()); // @formatter:on } static List selectDirectories(String... paths) { Preconditions.notNull(paths, "Directory paths must not be null"); Preconditions.containsNoNullElements(paths, "Individual directory paths must not be null"); // @formatter:off return uniqueStreamOf(paths) .filter(StringUtils::isNotBlank) .map(DiscoverySelectors::selectDirectory) .collect(Collectors.toList()); // @formatter:on } static List selectPackages(String... packageNames) { Preconditions.notNull(packageNames, "Package names must not be null"); Preconditions.containsNoNullElements(packageNames, "Individual package names must not be null"); // @formatter:off return uniqueStreamOf(packageNames) .map(DiscoverySelectors::selectPackage) .collect(Collectors.toList()); // @formatter:on } static Stream selectClasses(Class... classes) { Preconditions.notNull(classes, "classes must not be null"); Preconditions.containsNoNullElements(classes, "Individual classes must not be null"); return uniqueStreamOf(classes).map(DiscoverySelectors::selectClass); } static Stream selectClasses(String... classNames) { Preconditions.notNull(classNames, "classNames must not be null"); Preconditions.containsNoNullElements(classNames, "Individual class names must not be null"); return uniqueStreamOf(classNames).map(DiscoverySelectors::selectClass); } static List selectModules(String... moduleNames) { Preconditions.notNull(moduleNames, "Module names must not be null"); Preconditions.containsNoNullElements(moduleNames, "Individual module names must not be null"); return DiscoverySelectors.selectModules(uniqueStreamOf(moduleNames).collect(Collectors.toSet())); } static FileSelector selectFile(String path, int line, int column) { Preconditions.notBlank(path, "File path must not be null or blank"); if (line <= 0) { return DiscoverySelectors.selectFile(path); } if (column <= 0) { return DiscoverySelectors.selectFile(path, FilePosition.from(line)); } return DiscoverySelectors.selectFile(path, FilePosition.from(line, column)); } static ClasspathResourceSelector selectClasspathResource(String classpathResourceName, int line, int column) { Preconditions.notBlank(classpathResourceName, "Classpath resource name must not be null or blank"); if (line <= 0) { return DiscoverySelectors.selectClasspathResource(classpathResourceName); } if (column <= 0) { return DiscoverySelectors.selectClasspathResource(classpathResourceName, FilePosition.from(line)); } return DiscoverySelectors.selectClasspathResource(classpathResourceName, FilePosition.from(line, column)); } private static Stream uniqueStreamOf(T[] elements) { return Arrays.stream(elements).distinct(); } } SuiteLauncherDiscoveryRequestBuilder.java000066400000000000000000000335211455764576500421210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.commons; import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; import static org.junit.platform.suite.commons.AdditionalDiscoverySelectors.selectClasspathResource; import static org.junit.platform.suite.commons.AdditionalDiscoverySelectors.selectFile; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Stream; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.Filter; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.launcher.EngineFilter; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TagFilter; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.DisableParentConfigurationParameters; import org.junit.platform.suite.api.ExcludeClassNamePatterns; import org.junit.platform.suite.api.ExcludeEngines; import org.junit.platform.suite.api.ExcludePackages; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.IncludePackages; import org.junit.platform.suite.api.IncludeTags; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.SelectDirectories; import org.junit.platform.suite.api.SelectFile; import org.junit.platform.suite.api.SelectMethod; import org.junit.platform.suite.api.SelectModules; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.SelectUris; /** * @since 1.8 */ @API(status = Status.INTERNAL, since = "1.8", consumers = { "org.junit.platform.suite.engine", "org.junit.platform.runner" }) public final class SuiteLauncherDiscoveryRequestBuilder { private final LauncherDiscoveryRequestBuilder delegate = LauncherDiscoveryRequestBuilder.request(); private final Set selectedClassNames = new LinkedHashSet<>(); private boolean includeClassNamePatternsUsed; private boolean filterStandardClassNamePatterns = false; private ConfigurationParameters parentConfigurationParameters; private boolean enableParentConfigurationParameters = true; private SuiteLauncherDiscoveryRequestBuilder() { } public static SuiteLauncherDiscoveryRequestBuilder request() { return new SuiteLauncherDiscoveryRequestBuilder(); } public SuiteLauncherDiscoveryRequestBuilder filterStandardClassNamePatterns( boolean filterStandardClassNamePatterns) { this.filterStandardClassNamePatterns = filterStandardClassNamePatterns; return this; } public SuiteLauncherDiscoveryRequestBuilder selectors(DiscoverySelector... selectors) { delegate.selectors(selectors); return this; } public SuiteLauncherDiscoveryRequestBuilder selectors(List selectors) { delegate.selectors(selectors); return this; } public SuiteLauncherDiscoveryRequestBuilder filters(Filter... filters) { delegate.filters(filters); return this; } public SuiteLauncherDiscoveryRequestBuilder configurationParameter(String key, String value) { delegate.configurationParameter(key, value); return this; } public SuiteLauncherDiscoveryRequestBuilder configurationParameters(Map configurationParameters) { delegate.configurationParameters(configurationParameters); return this; } public SuiteLauncherDiscoveryRequestBuilder parentConfigurationParameters( ConfigurationParameters parentConfigurationParameters) { this.parentConfigurationParameters = parentConfigurationParameters; return this; } public SuiteLauncherDiscoveryRequestBuilder enableImplicitConfigurationParameters(boolean enabled) { delegate.enableImplicitConfigurationParameters(enabled); return this; } public SuiteLauncherDiscoveryRequestBuilder suite(Class suiteClass) { Preconditions.notNull(suiteClass, "Suite class must not be null"); // Annotations in alphabetical order (except @SelectClasses) // @formatter:off findRepeatableAnnotations(suiteClass, ConfigurationParameter.class) .forEach(configuration -> configurationParameter(configuration.key(), configuration.value())); findAnnotation(suiteClass, DisableParentConfigurationParameters.class) .ifPresent(__ -> enableParentConfigurationParameters = false); findAnnotationValues(suiteClass, ExcludeClassNamePatterns.class, ExcludeClassNamePatterns::value) .flatMap(SuiteLauncherDiscoveryRequestBuilder::trimmed) .map(ClassNameFilter::excludeClassNamePatterns) .ifPresent(this::filters); findAnnotationValues(suiteClass, ExcludeEngines.class, ExcludeEngines::value) .map(EngineFilter::excludeEngines) .ifPresent(this::filters); findAnnotationValues(suiteClass, ExcludePackages.class, ExcludePackages::value) .map(PackageNameFilter::excludePackageNames) .ifPresent(this::filters); findAnnotationValues(suiteClass, ExcludeTags.class, ExcludeTags::value) .map(TagFilter::excludeTags) .ifPresent(this::filters); // Process @SelectClasses before @IncludeClassNamePatterns, since the names // of selected classes get automatically added to the include filter. findAnnotation(suiteClass, SelectClasses.class) .map(annotation -> selectClasses(suiteClass, annotation)) .ifPresent(this::selectors); findRepeatableAnnotations(suiteClass, SelectMethod.class) .stream() .map(annotation -> selectMethod(suiteClass, annotation)) .forEach(this::selectors); findAnnotationValues(suiteClass, IncludeClassNamePatterns.class, IncludeClassNamePatterns::value) .flatMap(SuiteLauncherDiscoveryRequestBuilder::trimmed) .map(this::createIncludeClassNameFilter) .ifPresent(filters -> { includeClassNamePatternsUsed = true; filters(filters); }); findAnnotationValues(suiteClass, IncludeEngines.class, IncludeEngines::value) .map(EngineFilter::includeEngines) .ifPresent(this::filters); findAnnotationValues(suiteClass, IncludePackages.class, IncludePackages::value) .map(PackageNameFilter::includePackageNames) .ifPresent(this::filters); findAnnotationValues(suiteClass, IncludeTags.class, IncludeTags::value) .map(TagFilter::includeTags) .ifPresent(this::filters); findRepeatableAnnotations(suiteClass, SelectClasspathResource.class) .stream() .map(annotation -> selectClasspathResource(annotation.value(), annotation.line(), annotation.column())) .forEach(this::selectors); findAnnotationValues(suiteClass, SelectDirectories.class, SelectDirectories::value) .map(AdditionalDiscoverySelectors::selectDirectories) .ifPresent(this::selectors); findRepeatableAnnotations(suiteClass, SelectFile.class) .stream() .map(annotation -> selectFile(annotation.value(), annotation.line(), annotation.column())) .forEach(this::selectors); findAnnotationValues(suiteClass, SelectModules.class, SelectModules::value) .map(AdditionalDiscoverySelectors::selectModules) .ifPresent(this::selectors); findAnnotationValues(suiteClass, SelectUris.class, SelectUris::value) .map(AdditionalDiscoverySelectors::selectUris) .ifPresent(this::selectors); findAnnotationValues(suiteClass, SelectPackages.class, SelectPackages::value) .map(AdditionalDiscoverySelectors::selectPackages) .ifPresent(this::selectors); // @formatter:on return this; } public LauncherDiscoveryRequest build() { if (filterStandardClassNamePatterns && !includeClassNamePatternsUsed) { delegate.filters(createIncludeClassNameFilter(STANDARD_INCLUDE_PATTERN)); } if (enableParentConfigurationParameters && parentConfigurationParameters != null) { delegate.parentConfigurationParameters(parentConfigurationParameters); } return delegate.build(); } private List selectClasses(Class suiteClass, SelectClasses annotation) { return toClassSelectors(suiteClass, annotation) // .distinct() // .peek(selector -> this.selectedClassNames.add(selector.getClassName())) // .collect(toList()); } private static Stream toClassSelectors(Class suiteClass, SelectClasses annotation) { Preconditions.condition(annotation.value().length > 0 || annotation.names().length > 0, () -> String.format("@SelectClasses on class [%s] must declare at least one class reference or name", suiteClass.getName())); return Stream.concat(// AdditionalDiscoverySelectors.selectClasses(annotation.value()), // AdditionalDiscoverySelectors.selectClasses(annotation.names()) // ); } private MethodSelector selectMethod(Class suiteClass, SelectMethod annotation) { MethodSelector methodSelector = toMethodSelector(suiteClass, annotation); selectedClassNames.add(methodSelector.getClassName()); return methodSelector; } private MethodSelector toMethodSelector(Class suiteClass, SelectMethod annotation) { if (!annotation.value().isEmpty()) { Preconditions.condition(annotation.type() == Class.class, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "type must not be set in conjunction with fully qualified method name")); Preconditions.condition(annotation.typeName().isEmpty(), () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "type name must not be set in conjunction with fully qualified method name")); Preconditions.condition(annotation.name().isEmpty(), () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "method name must not be set in conjunction with fully qualified method name")); Preconditions.condition(annotation.parameterTypes().length == 0, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "parameter types must not be set in conjunction with fully qualified method name")); Preconditions.condition(annotation.parameterTypeNames().isEmpty(), () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "parameter type names must not be set in conjunction with fully qualified method name")); return DiscoverySelectors.selectMethod(annotation.value()); } Class type = annotation.type() == Class.class ? null : annotation.type(); String typeName = annotation.typeName().isEmpty() ? null : annotation.typeName().trim(); String methodName = Preconditions.notBlank(annotation.name(), () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "method name must not be blank")); Class[] parameterTypes = annotation.parameterTypes().length == 0 ? null : annotation.parameterTypes(); String parameterTypeNames = annotation.parameterTypeNames().trim(); if (parameterTypes != null) { Preconditions.condition(parameterTypeNames.isEmpty(), () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "either parameter type names or parameter types must be set but not both")); } if (type == null) { Preconditions.notBlank(typeName, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "type must be set or type name must not be blank")); if (parameterTypes == null) { return DiscoverySelectors.selectMethod(typeName, methodName, parameterTypeNames); } else { return DiscoverySelectors.selectMethod(typeName, methodName, parameterTypes); } } else { Preconditions.condition(typeName == null, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, "either type name or type must be set but not both")); if (parameterTypes == null) { return DiscoverySelectors.selectMethod(type, methodName, parameterTypeNames); } else { return DiscoverySelectors.selectMethod(type, methodName, parameterTypes); } } } private static String prefixErrorMessageForInvalidSelectMethodUsage(Class suiteClass, String detailMessage) { return String.format("@SelectMethod on class [%s]: %s", suiteClass.getName(), detailMessage); } private ClassNameFilter createIncludeClassNameFilter(String... patterns) { String[] combinedPatterns = Stream.concat(// this.selectedClassNames.stream().map(Pattern::quote), // Arrays.stream(patterns)// ).toArray(String[]::new); return ClassNameFilter.includeClassNamePatterns(combinedPatterns); } private static Optional findAnnotationValues(AnnotatedElement element, Class annotationType, Function valueExtractor) { return findAnnotation(element, annotationType).map(valueExtractor).filter(values -> values.length > 0); } private static Optional trimmed(String[] patterns) { if (patterns.length == 0) { return Optional.empty(); } // @formatter:off return Optional.of(Arrays.stream(patterns) .filter(StringUtils::isNotBlank) .map(String::trim) .toArray(String[]::new)); // @formatter:on } } package-info.java000066400000000000000000000005621455764576500351210ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/** * Common support utilities for executing test suites on the JUnit Platform. * *

DISCLAIMER

* *

Any API annotated with {@code @API(status = INTERNAL)} is intended solely * for usage within the JUnit framework itself. Any usage of internal * APIs by external parties is not supported! */ package org.junit.platform.suite.commons; junit5-r5.10.2/junit-platform-suite-commons/src/module/000077500000000000000000000000001455764576500230565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/000077500000000000000000000000001455764576500314225ustar00rootroot00000000000000module-info.java000066400000000000000000000014101455764576500344200ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/* * Copyright 2015-2020 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Common support utilities for declarative test suite executors. * * @since 1.8 */ module org.junit.platform.suite.commons { requires static transitive org.apiguardian.api; requires org.junit.platform.suite.api; requires org.junit.platform.commons; requires org.junit.platform.engine; requires transitive org.junit.platform.launcher; exports org.junit.platform.suite.commons to org.junit.platform.suite.engine, org.junit.platform.runner; } junit5-r5.10.2/junit-platform-suite-engine/000077500000000000000000000000001455764576500205745ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts000066400000000000000000000006321455764576500301220ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite Engine" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformEngine) api(projects.junitPlatformSuiteApi) compileOnlyApi(libs.apiguardian) implementation(projects.junitPlatformSuiteCommons) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-suite-engine/src/000077500000000000000000000000001455764576500213635ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/000077500000000000000000000000001455764576500223075ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/000077500000000000000000000000001455764576500232305ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/000077500000000000000000000000001455764576500240175ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/000077500000000000000000000000001455764576500251505ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500267745ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/000077500000000000000000000000001455764576500301255ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/000077500000000000000000000000001455764576500313725ustar00rootroot00000000000000ClassSelectorResolver.java000066400000000000000000000115121455764576500364460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.UniqueId.Segment; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.discovery.SelectorResolver; /** * @since 1.8 */ final class ClassSelectorResolver implements SelectorResolver { private static final Logger log = LoggerFactory.getLogger(ClassSelectorResolver.class); private static final IsSuiteClass isSuiteClass = new IsSuiteClass(); private final Predicate classNameFilter; private final SuiteEngineDescriptor suiteEngineDescriptor; private final ConfigurationParameters configurationParameters; ClassSelectorResolver(Predicate classNameFilter, SuiteEngineDescriptor suiteEngineDescriptor, ConfigurationParameters configurationParameters) { this.classNameFilter = classNameFilter; this.suiteEngineDescriptor = suiteEngineDescriptor; this.configurationParameters = configurationParameters; } @Override public Resolution resolve(ClassSelector selector, Context context) { Class testClass = selector.getJavaClass(); if (isSuiteClass.test(testClass)) { if (classNameFilter.test(testClass.getName())) { // @formatter:off Optional suiteWithDiscoveryRequest = context .addToParent(parent -> newSuiteDescriptor(testClass, parent)) .map(suite -> suite.addDiscoveryRequestFrom(testClass)); return toResolution(suiteWithDiscoveryRequest); // @formatter:on } } return unresolved(); } @Override public Resolution resolve(UniqueIdSelector selector, Context context) { UniqueId uniqueId = selector.getUniqueId(); UniqueId engineId = suiteEngineDescriptor.getUniqueId(); List resolvedSegments = engineId.getSegments(); // @formatter:off return uniqueId.getSegments() .stream() .skip(resolvedSegments.size()) .findFirst() .filter(suiteSegment -> SuiteTestDescriptor.SEGMENT_TYPE.equals(suiteSegment.getType())) .flatMap(ClassSelectorResolver::tryLoadSuiteClass) .filter(isSuiteClass) .map(suiteClass -> context .addToParent(parent -> newSuiteDescriptor(suiteClass, parent)) .map(suite -> uniqueId.equals(suite.getUniqueId()) // The uniqueId selector either targeted a class annotated with @Suite; ? suite.addDiscoveryRequestFrom(suiteClass) // or a specific test in that suite : suite.addDiscoveryRequestFrom(uniqueId))) .map(ClassSelectorResolver::toResolution) .orElseGet(Resolution::unresolved); // @formatter:on } private static Optional> tryLoadSuiteClass(UniqueId.Segment segment) { return ReflectionUtils.tryToLoadClass(segment.getValue()).toOptional(); } private static Resolution toResolution(Optional suite) { return suite.map(Match::exact).map(Resolution::match).orElseGet(Resolution::unresolved); } private Optional newSuiteDescriptor(Class suiteClass, TestDescriptor parent) { UniqueId id = parent.getUniqueId().append(SuiteTestDescriptor.SEGMENT_TYPE, suiteClass.getName()); if (containsCycle(id)) { log.config(() -> createConfigContainsCycleMessage(suiteClass, id)); return Optional.empty(); } return Optional.of(new SuiteTestDescriptor(id, suiteClass, configurationParameters)); } private static boolean containsCycle(UniqueId id) { List segments = id.getSegments(); List engineAndSuiteSegment = segments.subList(segments.size() - 2, segments.size()); List ancestorSegments = segments.subList(0, segments.size() - 2); for (int i = 0; i < ancestorSegments.size() - 1; i++) { List candidate = ancestorSegments.subList(i, i + 2); if (engineAndSuiteSegment.equals(candidate)) { return true; } } return false; } private static String createConfigContainsCycleMessage(Class suiteClass, UniqueId suiteId) { return String.format( "The suite configuration of [%s] resulted in a cycle [%s] and will not be discovered a second time.", suiteClass.getName(), suiteId); } } DiscoverySelectorResolver.java000066400000000000000000000030231455764576500373460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; /** * @since 1.8 */ final class DiscoverySelectorResolver { // @formatter:off private static final EngineDiscoveryRequestResolver resolver = EngineDiscoveryRequestResolver.builder() .addClassContainerSelectorResolver(new IsSuiteClass()) .addSelectorResolver(context -> new ClassSelectorResolver( context.getClassNameFilter(), context.getEngineDescriptor(), context.getDiscoveryRequest().getConfigurationParameters())) .build(); // @formatter:on private static void discoverSuites(SuiteEngineDescriptor engineDescriptor) { // @formatter:off engineDescriptor.getChildren().stream() .map(SuiteTestDescriptor.class::cast) .forEach(SuiteTestDescriptor::discover); // @formatter:on } void resolveSelectors(EngineDiscoveryRequest request, SuiteEngineDescriptor engineDescriptor) { resolver.resolve(request, engineDescriptor); discoverSuites(engineDescriptor); engineDescriptor.accept(TestDescriptor::prune); } } IsPotentialTestContainer.java000066400000000000000000000021031455764576500371100ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static org.junit.platform.commons.util.ReflectionUtils.isAbstract; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; import java.util.function.Predicate; /** * @since 1.8 */ final class IsPotentialTestContainer implements Predicate> { @Override public boolean test(Class candidate) { // Please do not collapse the following into a single statement. if (isPrivate(candidate)) { return false; } if (isAbstract(candidate)) { return false; } if (candidate.isLocalClass()) { return false; } if (candidate.isAnonymousClass()) { return false; } return !isInnerClass(candidate); } } IsSuiteClass.java000066400000000000000000000016761455764576500345430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import java.util.function.Predicate; import org.junit.platform.commons.support.AnnotationSupport; import org.junit.platform.suite.api.Suite; /** * @since 1.8 */ final class IsSuiteClass implements Predicate> { private static final IsPotentialTestContainer isPotentialTestContainer = new IsPotentialTestContainer(); @Override public boolean test(Class testClass) { return isPotentialTestContainer.test(testClass) && hasSuiteAnnotation(testClass); } private boolean hasSuiteAnnotation(Class testClass) { return AnnotationSupport.isAnnotated(testClass, Suite.class); } } NoTestsDiscoveredException.java000066400000000000000000000012261455764576500374450ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import org.junit.platform.commons.JUnitException; class NoTestsDiscoveredException extends JUnitException { private static final long serialVersionUID = 1L; NoTestsDiscoveredException(Class suiteClass) { super(String.format("Suite [%s] did not discover any tests", suiteClass.getName())); } } SuiteEngineDescriptor.java000066400000000000000000000014031455764576500364320ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; /** * @since 1.8 */ final class SuiteEngineDescriptor extends EngineDescriptor { static final String ENGINE_ID = "junit-platform-suite"; SuiteEngineDescriptor(UniqueId uniqueId) { super(uniqueId, "JUnit Platform Suite"); } @Override public Type getType() { return Type.CONTAINER; } } SuiteLauncher.java000066400000000000000000000052471455764576500347410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static java.util.Collections.emptyList; import java.util.LinkedHashSet; import java.util.Set; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.EngineDiscoveryOrchestrator; import org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.Phase; import org.junit.platform.launcher.core.EngineExecutionOrchestrator; import org.junit.platform.launcher.core.LauncherDiscoveryResult; import org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry; import org.junit.platform.launcher.listeners.SummaryGeneratingListener; import org.junit.platform.launcher.listeners.TestExecutionSummary; /** * @since 1.8 */ class SuiteLauncher { private final EngineExecutionOrchestrator executionOrchestrator = new EngineExecutionOrchestrator(); private final EngineDiscoveryOrchestrator discoveryOrchestrator; static SuiteLauncher create() { Set engines = new LinkedHashSet<>(); new ServiceLoaderTestEngineRegistry().loadTestEngines().forEach(engines::add); return new SuiteLauncher(engines); } private SuiteLauncher(Set testEngines) { Preconditions.condition(hasTestEngineOtherThanSuiteEngine(testEngines), () -> "Cannot create SuiteLauncher without at least one other TestEngine; " + "consider adding an engine implementation JAR to the classpath"); this.discoveryOrchestrator = new EngineDiscoveryOrchestrator(testEngines, emptyList()); } private boolean hasTestEngineOtherThanSuiteEngine(Set testEngines) { return testEngines.stream().anyMatch(testEngine -> !SuiteEngineDescriptor.ENGINE_ID.equals(testEngine.getId())); } LauncherDiscoveryResult discover(LauncherDiscoveryRequest discoveryRequest, UniqueId parentId) { return discoveryOrchestrator.discover(discoveryRequest, Phase.DISCOVERY, parentId); } TestExecutionSummary execute(LauncherDiscoveryResult discoveryResult, EngineExecutionListener parentEngineExecutionListener) { SummaryGeneratingListener listener = new SummaryGeneratingListener(); executionOrchestrator.execute(discoveryResult, parentEngineExecutionListener, listener); return listener.getSummary(); } } SuiteTestDescriptor.java000066400000000000000000000126511455764576500361530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder.request; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryResult; import org.junit.platform.launcher.listeners.TestExecutionSummary; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder; /** * {@link TestDescriptor} for tests based on the JUnit Platform Suite API. * *

Default Display Names

* *

The default display name is the simple name of the class. * * @since 1.8 * @see SuiteDisplayName */ final class SuiteTestDescriptor extends AbstractTestDescriptor { static final String SEGMENT_TYPE = "suite"; private final SuiteLauncherDiscoveryRequestBuilder discoveryRequestBuilder = request(); private final ConfigurationParameters configurationParameters; private final Boolean failIfNoTests; private final Class suiteClass; private LauncherDiscoveryResult launcherDiscoveryResult; private SuiteLauncher launcher; SuiteTestDescriptor(UniqueId id, Class suiteClass, ConfigurationParameters configurationParameters) { super(id, getSuiteDisplayName(suiteClass), ClassSource.from(suiteClass)); this.configurationParameters = configurationParameters; this.failIfNoTests = getFailIfNoTests(suiteClass); this.suiteClass = suiteClass; } private static Boolean getFailIfNoTests(Class suiteClass) { // @formatter:off return findAnnotation(suiteClass, Suite.class) .map(Suite::failIfNoTests) .orElseThrow(() -> new JUnitException(String.format("Suite [%s] was not annotated with @Suite", suiteClass.getName()))); // @formatter:on } SuiteTestDescriptor addDiscoveryRequestFrom(Class suiteClass) { Preconditions.condition(launcherDiscoveryResult == null, "discovery request can not be modified after discovery"); discoveryRequestBuilder.suite(suiteClass); return this; } SuiteTestDescriptor addDiscoveryRequestFrom(UniqueId uniqueId) { Preconditions.condition(launcherDiscoveryResult == null, "discovery request can not be modified after discovery"); discoveryRequestBuilder.selectors(DiscoverySelectors.selectUniqueId(uniqueId)); return this; } void discover() { if (launcherDiscoveryResult != null) { return; } // @formatter:off LauncherDiscoveryRequest request = discoveryRequestBuilder .filterStandardClassNamePatterns(true) .enableImplicitConfigurationParameters(false) .parentConfigurationParameters(configurationParameters) .build(); // @formatter:on this.launcher = SuiteLauncher.create(); this.launcherDiscoveryResult = launcher.discover(request, getUniqueId()); // @formatter:off launcherDiscoveryResult.getTestEngines() .stream() .map(testEngine -> launcherDiscoveryResult.getEngineTestDescriptor(testEngine)) .forEach(this::addChild); // @formatter:on } @Override public Type getType() { return Type.CONTAINER; } private static String getSuiteDisplayName(Class testClass) { // @formatter:off return findAnnotation(testClass, SuiteDisplayName.class) .map(SuiteDisplayName::value) .filter(StringUtils::isNotBlank) .orElse(testClass.getSimpleName()); // @formatter:on } void execute(EngineExecutionListener parentEngineExecutionListener) { parentEngineExecutionListener.executionStarted(this); // #2838: The discovery result from a suite may have been filtered by // post discovery filters from the launcher. The discovery result should // be pruned accordingly LauncherDiscoveryResult discoveryResult = this.launcherDiscoveryResult.withRetainedEngines( getChildren()::contains); TestExecutionSummary summary = launcher.execute(discoveryResult, parentEngineExecutionListener); parentEngineExecutionListener.executionFinished(this, computeTestExecutionResult(summary)); } private TestExecutionResult computeTestExecutionResult(TestExecutionSummary summary) { if (failIfNoTests && summary.getTestsFoundCount() == 0) { return TestExecutionResult.failed(new NoTestsDiscoveredException(suiteClass)); } return TestExecutionResult.successful(); } @Override public boolean mayRegisterTests() { // While a suite will not register new tests after discovery, we pretend // it does. This allows the suite to fail if not tests were discovered. // If not, the empty suite would be pruned. return true; } } SuiteTestEngine.java000066400000000000000000000046041455764576500352410ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; /** * The JUnit Platform Suite {@link org.junit.platform.engine.TestEngine TestEngine}. * * @since 1.8 */ @API(status = INTERNAL, since = "1.8") public final class SuiteTestEngine implements TestEngine { @Override public String getId() { return SuiteEngineDescriptor.ENGINE_ID; } /** * Returns {@code org.junit.platform} as the group ID. */ @Override public Optional getGroupId() { return Optional.of("org.junit.platform"); } /** * Returns {@code junit-platform-suite-engine} as the artifact ID. */ @Override public Optional getArtifactId() { return Optional.of("junit-platform-suite-engine"); } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { SuiteEngineDescriptor engineDescriptor = new SuiteEngineDescriptor(uniqueId); new DiscoverySelectorResolver().resolveSelectors(discoveryRequest, engineDescriptor); return engineDescriptor; } @Override public void execute(ExecutionRequest request) { SuiteEngineDescriptor suiteEngineDescriptor = (SuiteEngineDescriptor) request.getRootTestDescriptor(); EngineExecutionListener engineExecutionListener = request.getEngineExecutionListener(); engineExecutionListener.executionStarted(suiteEngineDescriptor); // @formatter:off suiteEngineDescriptor.getChildren() .stream() .map(SuiteTestDescriptor.class::cast) .forEach(suiteTestDescriptor -> suiteTestDescriptor.execute(engineExecutionListener)); // @formatter:on engineExecutionListener.executionFinished(suiteEngineDescriptor, TestExecutionResult.successful()); } } package-info.java000066400000000000000000000001541455764576500345020ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/** * Core package for the JUnit Platform Suite test engine. */ package org.junit.platform.suite.engine; junit5-r5.10.2/junit-platform-suite-engine/src/main/resources/000077500000000000000000000000001455764576500243215ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/resources/META-INF/000077500000000000000000000000001455764576500254615ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500273045ustar00rootroot00000000000000org.junit.platform.engine.TestEngine000066400000000000000000000000601455764576500362160ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/main/resources/META-INF/servicesorg.junit.platform.suite.engine.SuiteTestEngine junit5-r5.10.2/junit-platform-suite-engine/src/module/000077500000000000000000000000001455764576500226505ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/module/org.junit.platform.suite.engine/000077500000000000000000000000001455764576500310065ustar00rootroot00000000000000module-info.java000066400000000000000000000015561455764576500340170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite-engine/src/module/org.junit.platform.suite.engine/* * Copyright 2015-2020 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Provides a {@linkplain org.junit.platform.engine.TestEngine} for running * declarative test suites. * * @since 1.8 * @provides org.junit.platform.engine.TestEngine */ module org.junit.platform.suite.engine { requires static org.apiguardian.api; requires org.junit.platform.suite.api; requires org.junit.platform.suite.commons; requires org.junit.platform.commons; requires org.junit.platform.engine; requires org.junit.platform.launcher; provides org.junit.platform.engine.TestEngine with org.junit.platform.suite.engine.SuiteTestEngine; } junit5-r5.10.2/junit-platform-suite/000077500000000000000000000000001455764576500173315ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite/junit-platform-suite.gradle.kts000066400000000000000000000005301455764576500254110ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite (Aggregator)" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformSuiteApi) implementation(projects.junitPlatformSuiteEngine) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-suite/src/000077500000000000000000000000001455764576500201205ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite/src/module/000077500000000000000000000000001455764576500214055ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite/src/module/org.junit.platform.suite/000077500000000000000000000000001455764576500262775ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-suite/src/module/org.junit.platform.suite/module-info.java000066400000000000000000000010211455764576500313520ustar00rootroot00000000000000/* * Copyright 2015-2020 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Aggregates all JUnit Platform Suite modules. * * @since 1.8 */ module org.junit.platform.suite { requires transitive org.junit.platform.suite.api; requires transitive org.junit.platform.suite.engine; } junit5-r5.10.2/junit-platform-testkit/000077500000000000000000000000001455764576500176675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/LICENSE.md000066400000000000000000000336331455764576500213030ustar00rootroot00000000000000Eclipse Public License - v 2.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 content 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 changes or additions to the Program that are not Modified Works. “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 or any Secondary License (as applicable), including Contributors. “Derivative Works” shall mean any work, whether in Source Code or other form, that is based on (or derived from) the Program and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. “Modified Works” shall mean any work in Source Code or other form that results from an addition to, deletion from, or modification of the contents of the Program, including, for purposes of clarity any new file in Source Code form that contains any contents of the Program. Modified Works shall not include works that contain only declarations, interfaces, types, classes, structures, or files of the Program solely in each case in order to link to, bind by name, or subclass the Program or Modified Works thereof. “Distribute” means the acts of **a)** distributing or **b)** making available in any manner that enables the transfer of a copy. “Source Code” means the form of a Program preferred for making modifications, including but not limited to software source code, documentation source, and configuration files. “Secondary License” means either the GNU General Public License, Version 2.0, or any later versions of that license, including any exceptions or additional permissions as identified by the initial Contributor. ### 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. **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 or other 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. **e)** Notwithstanding the terms of any Secondary License, no Contributor makes additional grants to any Recipient (other than those set forth in this Agreement) as a result of such Recipient's receipt of the Program under the terms of a Secondary License (if permitted under the terms of Section 3). ### 3. Requirements **3.1** If a Contributor Distributes the Program in any form, then: * **a)** the Program must also be made available as Source Code, in accordance with section 3.2, and the Contributor must accompany the Program with a statement that the Source Code for the Program is available under this Agreement, and informs Recipients how to obtain it in a reasonable manner on or through a medium customarily used for software exchange; and * **b)** the Contributor may Distribute the Program under a license different than this Agreement, provided that such license: * **i)** effectively disclaims on behalf of all other 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 other Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; * **iii)** does not attempt to limit or alter the recipients' rights in the Source Code under section 3.2; and * **iv)** requires any subsequent distribution of the Program by any party to be under a license that satisfies the requirements of this section 3. **3.2** When the Program is Distributed as Source Code: * **a)** it must be made available under this Agreement, or if the Program **(i)** is combined with other material in a separate file or files made available under a Secondary License, and **(ii)** the initial Contributor attached to the Source Code the notice described in Exhibit A of this Agreement, then the Program may be made available under the terms of such Secondary Licenses, and * **b)** a copy of this Agreement must be included with each copy of the Program. **3.3** Contributors may not remove or alter any copyright, patent, trademark, attribution notices, disclaimers of warranty, or limitations of liability (“notices”) contained within the Program from any copy of the Program which they Distribute, provided that Contributors may add their own appropriate notices. ### 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, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, 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, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, 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. Nothing in this Agreement is intended to be enforceable by any entity that is not a Contributor or Recipient. No third-party beneficiary rights are created under this Agreement. #### Exhibit A - Form of Secondary Licenses Notice > “This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), version(s), and exceptions or additional permissions here}.” Simply including a copy of this Agreement, including this Exhibit A is not sufficient to license the Source Code under Secondary Licenses. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. junit5-r5.10.2/junit-platform-testkit/junit-platform-testkit.gradle.kts000066400000000000000000000005471455764576500263150ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") } description = "JUnit Platform Test Kit" dependencies { api(platform(projects.junitBom)) api(libs.assertj) api(libs.opentest4j) api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } junit5-r5.10.2/junit-platform-testkit/src/000077500000000000000000000000001455764576500204565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/000077500000000000000000000000001455764576500214025ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/000077500000000000000000000000001455764576500223235ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/000077500000000000000000000000001455764576500231125ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/000077500000000000000000000000001455764576500242435ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/000077500000000000000000000000001455764576500260675ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/000077500000000000000000000000001455764576500275565ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/000077500000000000000000000000001455764576500310235ustar00rootroot00000000000000Assertions.java000066400000000000000000000051201455764576500337370ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.AssertionFailedError; import org.opentest4j.MultipleFailuresError; /** * {@code Assertions} is a collection of selected assertion utility methods * from JUnit Jupiter for use within the JUnit Platform Test Kit. * * @since 1.4 */ class Assertions { @FunctionalInterface interface Executable { void execute() throws Throwable; } static void assertAll(String heading, Stream executables) { Preconditions.notNull(executables, "executables stream must not be null"); List failures = executables // .map(executable -> { Preconditions.notNull(executable, "individual executables must not be null"); try { executable.execute(); return null; } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); return t; } }) // .filter(Objects::nonNull) // .collect(Collectors.toList()); if (!failures.isEmpty()) { MultipleFailuresError multipleFailuresError = new MultipleFailuresError(heading, failures); failures.forEach(multipleFailuresError::addSuppressed); throw multipleFailuresError; } } static void assertEquals(long expected, long actual, String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } private static void failNotEqual(long expected, long actual, String message) { fail(format(expected, actual, message), expected, actual); } private static void fail(String message, Object expected, Object actual) { throw new AssertionFailedError(message, expected, actual); } private static String format(long expected, long actual, String message) { return buildPrefix(message) + formatValues(expected, actual); } private static String buildPrefix(String message) { return (StringUtils.isNotBlank(message) ? message + " ==> " : ""); } private static String formatValues(long expected, long actual) { return String.format("expected: <%d> but was: <%d>", expected, actual); } } EngineExecutionResults.java000066400000000000000000000057421455764576500362720ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.testkit.engine.Event.byTestDescriptor; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; /** * {@code EngineExecutionResults} provides a fluent API for processing the * results of executing a test plan on the JUnit Platform for a given * {@link org.junit.platform.engine.TestEngine TestEngine}. * * @since 1.4 * @see #allEvents() * @see #containerEvents() * @see #testEvents() * @see ExecutionRecorder * @see Events * @see Executions */ @API(status = MAINTAINED, since = "1.7") public class EngineExecutionResults { private final Events allEvents; private final Events testEvents; private final Events containerEvents; /** * Construct {@link EngineExecutionResults} from the supplied list of recorded * {@linkplain Event events}. * * @param events the list of events; never {@code null} or * containing {@code null} elements */ EngineExecutionResults(List events) { Preconditions.notNull(events, "Event list must not be null"); Preconditions.containsNoNullElements(events, "Event list must not contain null elements"); this.allEvents = new Events(events, "All"); this.testEvents = new Events(filterEvents(events, TestDescriptor::isTest), "Test"); this.containerEvents = new Events(filterEvents(events, TestDescriptor::isContainer), "Container"); } /** * Get all recorded events. * * @since 1.6 * @see #containerEvents() * @see #testEvents() */ public Events allEvents() { return this.allEvents; } /** * Get recorded events for containers. * *

In this context, the word "container" applies to {@link TestDescriptor * TestDescriptors} that return {@code true} from {@link TestDescriptor#isContainer()}. * * @since 1.6 * @see #allEvents() * @see #testEvents() */ public Events containerEvents() { return this.containerEvents; } /** * Get recorded events for tests. * *

In this context, the word "test" applies to {@link TestDescriptor * TestDescriptors} that return {@code true} from {@link TestDescriptor#isTest()}. * * @since 1.6 * @see #allEvents() * @see #containerEvents() */ public Events testEvents() { return this.testEvents; } /** * Filter the supplied list of events using the supplied predicate. */ private static Stream filterEvents(List events, Predicate predicate) { return events.stream().filter(byTestDescriptor(predicate)); } } EngineTestKit.java000066400000000000000000000430011455764576500343220ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.Phase.EXECUTION; import java.util.Map; import java.util.ServiceLoader; import java.util.stream.Stream; import org.apiguardian.api.API; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.Filter; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.EngineDiscoveryOrchestrator; import org.junit.platform.launcher.core.EngineExecutionOrchestrator; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherDiscoveryResult; import org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry; /** * {@code EngineTestKit} provides support for executing a test plan for a given * {@link TestEngine} and then accessing the results via * {@linkplain EngineExecutionResults a fluent API} to verify the expected results. * * @since 1.4 * @see #engine(String) * @see #engine(TestEngine) * @see #execute(String, LauncherDiscoveryRequest) * @see #execute(TestEngine, LauncherDiscoveryRequest) * @see EngineExecutionResults */ @API(status = MAINTAINED, since = "1.7") public final class EngineTestKit { /** * Create an execution {@link Builder} for the {@link TestEngine} with the * supplied ID. * *

The {@code TestEngine} will be loaded via Java's {@link ServiceLoader} * mechanism, analogous to the manner in which test engines are loaded in * the JUnit Platform Launcher API. * *

Example Usage

* *
	 * EngineTestKit
	 *     .engine("junit-jupiter")
	 *     .selectors(selectClass(MyTests.class))
	 *     .execute()
	 *     .testEvents()
	 *     .assertStatistics(stats -> stats.started(2).finished(2));
	 * 
* * @param engineId the ID of the {@code TestEngine} to use; must not be * {@code null} or blank * @return the engine execution {@code Builder} * @throws PreconditionViolationException if the supplied ID is {@code null} * or blank, or if the {@code TestEngine} with the supplied ID * cannot be loaded * @see #engine(TestEngine) * @see #execute(String, LauncherDiscoveryRequest) * @see #execute(TestEngine, LauncherDiscoveryRequest) */ public static Builder engine(String engineId) { Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); return engine(loadTestEngine(engineId.trim())); } /** * Create an execution {@link Builder} for the supplied {@link TestEngine}. * *

Example Usage

* *
	 * EngineTestKit
	 *     .engine(new MyTestEngine())
	 *     .selectors(selectClass(MyTests.class))
	 *     .execute()
	 *     .testEvents()
	 *     .assertStatistics(stats -> stats.started(2).finished(2));
	 * 
* * @param testEngine the {@code TestEngine} to use; must not be {@code null} * @return the engine execution {@code Builder} * @throws PreconditionViolationException if the {@code TestEngine} is * {@code null} * @see #engine(String) * @see #execute(String, LauncherDiscoveryRequest) * @see #execute(TestEngine, LauncherDiscoveryRequest) */ public static Builder engine(TestEngine testEngine) { Preconditions.notNull(testEngine, "TestEngine must not be null"); return new Builder(testEngine); } /** * Execute tests for the given {@link EngineDiscoveryRequest} using the * {@link TestEngine} with the supplied ID. * *

The {@code TestEngine} will be loaded via Java's {@link ServiceLoader} * mechanism, analogous to the manner in which test engines are loaded in * the JUnit Platform Launcher API. * *

Note that {@link org.junit.platform.launcher.LauncherDiscoveryRequest} * from the {@code junit-platform-launcher} module is a subtype of * {@code EngineDiscoveryRequest}. It is therefore quite convenient to make * use of the DSL provided in * {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} * to build an appropriate discovery request to supply to this method. As * an alternative, consider using {@link #engine(String)} for a more fluent * API. * * @param engineId the ID of the {@code TestEngine} to use; must not be * {@code null} or blank * @param discoveryRequest the {@code EngineDiscoveryRequest} to use * @return the results of the execution * @throws PreconditionViolationException for invalid arguments or if the * {@code TestEngine} with the supplied ID cannot be loaded * @see #execute(String, LauncherDiscoveryRequest) * @see #engine(String) * @see #engine(TestEngine) * @deprecated Please use {@link #execute(String, LauncherDiscoveryRequest)} * instead. */ @Deprecated @API(status = DEPRECATED, since = "1.7") public static EngineExecutionResults execute(String engineId, EngineDiscoveryRequest discoveryRequest) { Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); return execute(loadTestEngine(engineId.trim()), discoveryRequest); } /** * Execute tests for the given {@link LauncherDiscoveryRequest} using the * {@link TestEngine} with the supplied ID. * *

The {@code TestEngine} will be loaded via Java's {@link ServiceLoader} * mechanism, analogous to the manner in which test engines are loaded in * the JUnit Platform Launcher API. * *

{@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} * provides a convenient way to build an appropriate discovery request to * supply to this method. As an alternative, consider using * {@link #engine(TestEngine)} for a more fluent API. * * @param engineId the ID of the {@code TestEngine} to use; must not be * {@code null} or blank * @param discoveryRequest the {@code LauncherDiscoveryRequest} to use * @return the results of the execution * @throws PreconditionViolationException for invalid arguments or if the * {@code TestEngine} with the supplied ID cannot be loaded * @since 1.7 * @see #execute(TestEngine, LauncherDiscoveryRequest) * @see #engine(String) * @see #engine(TestEngine) */ public static EngineExecutionResults execute(String engineId, LauncherDiscoveryRequest discoveryRequest) { Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); return execute(loadTestEngine(engineId.trim()), discoveryRequest); } /** * Execute tests for the given {@link EngineDiscoveryRequest} using the * supplied {@link TestEngine}. * *

Note that {@link org.junit.platform.launcher.LauncherDiscoveryRequest} * from the {@code junit-platform-launcher} module is a subtype of * {@code EngineDiscoveryRequest}. It is therefore quite convenient to make * use of the DSL provided in * {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} * to build an appropriate discovery request to supply to this method. As * an alternative, consider using {@link #engine(TestEngine)} for a more fluent * API. * * @param testEngine the {@code TestEngine} to use; must not be {@code null} * @param discoveryRequest the {@code EngineDiscoveryRequest} to use; must * not be {@code null} * @return the recorded {@code EngineExecutionResults} * @throws PreconditionViolationException for invalid arguments * @see #execute(TestEngine, LauncherDiscoveryRequest) * @see #engine(String) * @see #engine(TestEngine) * @deprecated Please use {@link #execute(TestEngine, LauncherDiscoveryRequest)} * instead. */ @Deprecated @API(status = DEPRECATED, since = "1.7") public static EngineExecutionResults execute(TestEngine testEngine, EngineDiscoveryRequest discoveryRequest) { Preconditions.notNull(testEngine, "TestEngine must not be null"); Preconditions.notNull(discoveryRequest, "EngineDiscoveryRequest must not be null"); ExecutionRecorder executionRecorder = new ExecutionRecorder(); executeDirectly(testEngine, discoveryRequest, executionRecorder); return executionRecorder.getExecutionResults(); } /** * Execute tests for the given {@link LauncherDiscoveryRequest} using the * supplied {@link TestEngine}. * *

{@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} * provides a convenient way to build an appropriate discovery request to * supply to this method. As an alternative, consider using * {@link #engine(TestEngine)} for a more fluent API. * * @param testEngine the {@code TestEngine} to use; must not be {@code null} * @param discoveryRequest the {@code LauncherDiscoveryRequest} to use; must * not be {@code null} * @return the recorded {@code EngineExecutionResults} * @throws PreconditionViolationException for invalid arguments * @since 1.7 * @see #execute(String, LauncherDiscoveryRequest) * @see #engine(String) * @see #engine(TestEngine) */ public static EngineExecutionResults execute(TestEngine testEngine, LauncherDiscoveryRequest discoveryRequest) { Preconditions.notNull(testEngine, "TestEngine must not be null"); Preconditions.notNull(discoveryRequest, "EngineDiscoveryRequest must not be null"); ExecutionRecorder executionRecorder = new ExecutionRecorder(); executeUsingLauncherOrchestration(testEngine, discoveryRequest, executionRecorder); return executionRecorder.getExecutionResults(); } private static void executeDirectly(TestEngine testEngine, EngineDiscoveryRequest discoveryRequest, EngineExecutionListener listener) { UniqueId engineUniqueId = UniqueId.forEngine(testEngine.getId()); TestDescriptor engineTestDescriptor = testEngine.discover(discoveryRequest, engineUniqueId); ExecutionRequest request = new ExecutionRequest(engineTestDescriptor, listener, discoveryRequest.getConfigurationParameters()); testEngine.execute(request); } private static void executeUsingLauncherOrchestration(TestEngine testEngine, LauncherDiscoveryRequest discoveryRequest, EngineExecutionListener listener) { LauncherDiscoveryResult discoveryResult = new EngineDiscoveryOrchestrator(singleton(testEngine), emptySet()).discover(discoveryRequest, EXECUTION); TestDescriptor engineTestDescriptor = discoveryResult.getEngineTestDescriptor(testEngine); Preconditions.notNull(engineTestDescriptor, "TestEngine did not yield a TestDescriptor"); new EngineExecutionOrchestrator().execute(discoveryResult, listener); } @SuppressWarnings("unchecked") private static TestEngine loadTestEngine(String engineId) { Iterable testEngines = new ServiceLoaderTestEngineRegistry().loadTestEngines(); return ((Stream) CollectionUtils.toStream(testEngines)) // .filter((TestEngine engine) -> engineId.equals(engine.getId()))// .findFirst()// .orElseThrow(() -> new PreconditionViolationException( String.format("Failed to load TestEngine with ID [%s]", engineId))); } private EngineTestKit() { /* no-op */ } // ------------------------------------------------------------------------- /** * {@link TestEngine} execution builder. * *

See {@link EngineTestKit#engine(String)} and * {@link EngineTestKit#engine(TestEngine)} for example usage. * * @since 1.4 * @see #selectors(DiscoverySelector...) * @see #filters(Filter...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) * @see #execute() */ public static final class Builder { private final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request() // .enableImplicitConfigurationParameters(false); private final TestEngine testEngine; private Builder(TestEngine testEngine) { this.testEngine = testEngine; } /** * Add all of the supplied {@linkplain DiscoverySelector discovery selectors}. * *

Built-in discovery selectors can be created via the static factory * methods in {@link org.junit.platform.engine.discovery.DiscoverySelectors}. * * @param selectors the discovery selectors to add; never {@code null} * @return this builder for method chaining * @see #filters(Filter...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) * @see #execute() */ public Builder selectors(DiscoverySelector... selectors) { this.requestBuilder.selectors(selectors); return this; } /** * Add all of the supplied {@linkplain DiscoveryFilter discovery filters}. * *

Built-in discovery filters can be created via the static factory * methods in {@link org.junit.platform.engine.discovery.ClassNameFilter} * and {@link org.junit.platform.engine.discovery.PackageNameFilter}. * * @param filters the discovery filters to add; never {@code null} * @return this builder for method chaining * @see #filters(Filter...) * @see #selectors(DiscoverySelector...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) * @see #execute() * @deprecated Please use {@link #filters(Filter...)} instead. */ @Deprecated @API(status = DEPRECATED, since = "1.7") public Builder filters(DiscoveryFilter... filters) { this.requestBuilder.filters(filters); return this; } /** * Add all of the supplied {@linkplain Filter filters}. * *

Built-in discovery filters can be created via the static factory * methods in {@link org.junit.platform.engine.discovery.ClassNameFilter} * and {@link org.junit.platform.engine.discovery.PackageNameFilter}. * *

Built-in post-discovery filters can be created via the static * factory methods in {@link org.junit.platform.launcher.TagFilter}. * * @param filters the filters to add; never {@code null} * @return this builder for method chaining * @since 1.7 * @see #selectors(DiscoverySelector...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) * @see #execute() */ @API(status = STABLE, since = "1.10") public Builder filters(Filter... filters) { this.requestBuilder.filters(filters); return this; } /** * Add the supplied configuration parameter. * * @param key the configuration parameter key under which to store the * value; never {@code null} or blank * @param value the value to store * @return this builder for method chaining * @see #selectors(DiscoverySelector...) * @see #filters(Filter...) * @see #configurationParameters(Map) * @see #execute() * @see org.junit.platform.engine.ConfigurationParameters */ public Builder configurationParameter(String key, String value) { this.requestBuilder.configurationParameter(key, value); return this; } /** * Add all of the supplied configuration parameters. * * @param configurationParameters the map of configuration parameters to add; * never {@code null} * @return this builder for method chaining * @see #selectors(DiscoverySelector...) * @see #filters(Filter...) * @see #configurationParameter(String, String) * @see #execute() * @see org.junit.platform.engine.ConfigurationParameters */ public Builder configurationParameters(Map configurationParameters) { this.requestBuilder.configurationParameters(configurationParameters); return this; } /** * Configure whether implicit configuration parameters should be * considered. * *

By default, only configuration parameters that are passed * explicitly to this builder are taken into account. Passing * {@code true} to this method, enables additionally reading * configuration parameters from implicit sources, i.e. system * properties and the {@code junit-platform.properties} classpath * resource. * * @see #configurationParameter(String, String) * @see #configurationParameters(Map) */ @API(status = STABLE, since = "1.10") public Builder enableImplicitConfigurationParameters(boolean enabled) { this.requestBuilder.enableImplicitConfigurationParameters(enabled); return this; } /** * Execute tests for the configured {@link TestEngine}, * {@linkplain DiscoverySelector discovery selectors}, * {@linkplain DiscoveryFilter discovery filters}, and * configuration parameters. * * @return the recorded {@code EngineExecutionResults} * @see #selectors(DiscoverySelector...) * @see #filters(Filter...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) */ public EngineExecutionResults execute() { LauncherDiscoveryRequest request = this.requestBuilder.build(); ExecutionRecorder executionRecorder = new ExecutionRecorder(); EngineTestKit.executeUsingLauncherOrchestration(this.testEngine, request, executionRecorder); return executionRecorder.getExecutionResults(); } } } junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Event.java000066400000000000000000000214241455764576500327520ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; import java.time.Instant; import java.util.Optional; import java.util.function.Predicate; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; /** * {@code Event} represents a single event fired during execution of * a test plan on the JUnit Platform. * * @since 1.4 * @see EventType */ @API(status = MAINTAINED, since = "1.7") public class Event { // --- Factories ----------------------------------------------------------- /** * Create an {@code Event} for a reporting entry published for the * supplied {@link TestDescriptor} and {@link ReportEntry}. * * @param testDescriptor the {@code TestDescriptor} associated with the event; * never {@code null} * @param entry the {@code ReportEntry} that was published; never {@code null} * @return the newly created {@code Event} * @see EventType#REPORTING_ENTRY_PUBLISHED */ public static Event reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { Preconditions.notNull(entry, "ReportEntry must not be null"); return new Event(EventType.REPORTING_ENTRY_PUBLISHED, testDescriptor, entry); } /** * Create an {@code Event} for the dynamic registration of the * supplied {@link TestDescriptor}. * * @param testDescriptor the {@code TestDescriptor} associated with the event; * never {@code null} * @return the newly created {@code Event} * @see EventType#DYNAMIC_TEST_REGISTERED */ public static Event dynamicTestRegistered(TestDescriptor testDescriptor) { return new Event(EventType.DYNAMIC_TEST_REGISTERED, testDescriptor, null); } /** * Create a skipped {@code Event} for the supplied * {@link TestDescriptor} and {@code reason}. * * @param testDescriptor the {@code TestDescriptor} associated with the event; * never {@code null} * @param reason the reason the execution was skipped; may be {@code null} * @return the newly created {@code Event} * @see EventType#SKIPPED */ public static Event executionSkipped(TestDescriptor testDescriptor, String reason) { return new Event(EventType.SKIPPED, testDescriptor, reason); } /** * Create a started {@code Event} for the supplied * {@link TestDescriptor}. * * @param testDescriptor the {@code TestDescriptor} associated with the * event; never {@code null} * @return the newly created {@code Event} * @see EventType#STARTED */ public static Event executionStarted(TestDescriptor testDescriptor) { return new Event(EventType.STARTED, testDescriptor, null); } /** * Create a finished {@code Event} for the supplied * {@link TestDescriptor} and {@link TestExecutionResult}. * * @param testDescriptor the {@code TestDescriptor} associated with the * event; never {@code null} * @param result the {@code TestExecutionResult} for the supplied * {@code TestDescriptor}; never {@code null} * @return the newly created {@code Event} * @see EventType#FINISHED */ public static Event executionFinished(TestDescriptor testDescriptor, TestExecutionResult result) { Preconditions.notNull(result, "Event of type FINISHED cannot have a null TestExecutionResult"); return new Event(EventType.FINISHED, testDescriptor, result); } // --- Predicates ---------------------------------------------------------- /** * Create a {@link Predicate} for {@linkplain Event events} whose payload * types match the supplied {@code payloadType} and whose payloads match the * supplied {@code payloadPredicate}. * * @param payloadType the required payload type * @param payloadPredicate a {@code Predicate} to match against payloads * @return the resulting {@code Predicate} */ public static Predicate byPayload(Class payloadType, Predicate payloadPredicate) { return event -> event.getPayload(payloadType).filter(payloadPredicate).isPresent(); } /** * Create a {@link Predicate} for {@linkplain Event events} whose * {@linkplain EventType event types} match the supplied {@code type}. * * @param type the type to match against * @return the resulting {@code Predicate} */ public static Predicate byType(EventType type) { return event -> event.type.equals(type); } /** * Create a {@link Predicate} for {@linkplain Event events} whose * {@link TestDescriptor TestDescriptors} match the supplied * {@code testDescriptorPredicate}. * * @param testDescriptorPredicate a {@code Predicate} to match against test * descriptors * @return the resulting {@link Predicate} */ public static Predicate byTestDescriptor(Predicate testDescriptorPredicate) { return where(Event::getTestDescriptor, testDescriptorPredicate); } // ------------------------------------------------------------------------- private final Instant timestamp = Instant.now(); private final EventType type; private final TestDescriptor testDescriptor; private final Object payload; /** * Construct an {@code Event} with the supplied arguments. * * @param type the type of the event; never {@code null} * @param testDescriptor the {@code TestDescriptor} associated with the event; * never {@code null} * @param payload the generic payload associated with the event; may be {@code null} */ private Event(EventType type, TestDescriptor testDescriptor, Object payload) { this.type = Preconditions.notNull(type, "EventType must not be null"); this.testDescriptor = Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); this.payload = payload; } /** * Get the type of this {@code Event}. * * @return the event type; never {@code null} * @see EventType */ public EventType getType() { return this.type; } /** * Get the {@link TestDescriptor} associated with this {@code Event}. * * @return the {@code TestDescriptor}; never {@code null} */ public TestDescriptor getTestDescriptor() { return this.testDescriptor; } /** * Get the {@link Instant} when this {@code Event} occurred. * * @return the {@code Instant} when this {@code Event} occurred; * never {@code null} */ public Instant getTimestamp() { return this.timestamp; } /** * Get the payload, if available. * * @return an {@code Optional} containing the payload; never {@code null} * but potentially empty * @see #getPayload(Class) * @see #getRequiredPayload(Class) */ public Optional getPayload() { return Optional.ofNullable(this.payload); } /** * Get the payload of the expected type, if available. * *

This is a convenience method that automatically casts the payload to * the expected type. If the payload is not present or is not of the expected * type, this method will return {@link Optional#empty()}. * * @param payloadType the expected payload type; never {@code null} * @return an {@code Optional} containing the payload; never {@code null} * but potentially empty * @see #getPayload() * @see #getRequiredPayload(Class) */ public Optional getPayload(Class payloadType) { Preconditions.notNull(payloadType, "Payload type must not be null"); return getPayload().filter(payloadType::isInstance).map(payloadType::cast); } /** * Get the payload of the required type. * *

This is a convenience method that automatically casts the payload to * the required type. If the payload is not present or is not of the expected * type, this method will throw an {@link IllegalArgumentException}. * * @param payloadType the required payload type; never {@code null} * @return the payload * @throws IllegalArgumentException if the payload is of a different type * or is not present * @see #getPayload() * @see #getPayload(Class) */ public T getRequiredPayload(Class payloadType) throws IllegalArgumentException { return getPayload(payloadType).orElseThrow(// () -> new IllegalArgumentException("Event does not contain a payload of type " + payloadType.getName())); } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("type", this.type) .append("testDescriptor", this.testDescriptor) .append("timestamp", this.timestamp) .append("payload", this.payload) .toString(); // @formatter:on } } EventConditions.java000066400000000000000000000446461455764576500347400ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.assertj.core.api.Assertions.allOf; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import static org.junit.platform.testkit.engine.Event.byPayload; import static org.junit.platform.testkit.engine.Event.byTestDescriptor; import static org.junit.platform.testkit.engine.Event.byType; import static org.junit.platform.testkit.engine.EventType.DYNAMIC_TEST_REGISTERED; import static org.junit.platform.testkit.engine.EventType.FINISHED; import static org.junit.platform.testkit.engine.EventType.SKIPPED; import static org.junit.platform.testkit.engine.EventType.STARTED; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Predicate; import org.apiguardian.api.API; import org.assertj.core.api.Condition; import org.assertj.core.description.Description; import org.assertj.core.description.JoinDescription; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.EngineDescriptor; /** * Collection of AssertJ {@linkplain Condition conditions} for {@link Event}. * * @since 1.4 * @see TestExecutionResultConditions */ @API(status = MAINTAINED, since = "1.7") public final class EventConditions { private EventConditions() { /* no-op */ } /** * Create a new {@link Condition} that matches if and only if an * {@link Event} matches all of the supplied conditions. */ @SafeVarargs @SuppressWarnings("varargs") public static Condition event(Condition... conditions) { return allOf(conditions); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * an instance of {@link EngineDescriptor}. */ public static Condition engine() { return new Condition<>(byTestDescriptor(EngineDescriptor.class::isInstance), "is an engine"); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isTest() test} and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the supplied * {@link String}. * * @see #test() * @see #uniqueIdSubstring(String) */ public static Condition test(String uniqueIdSubstring) { return test(uniqueIdSubstring(uniqueIdSubstring)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isTest() test}, its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the supplied * {@link String}, and its {@linkplain TestDescriptor#getDisplayName() * display name} equals the supplied {@link String}. * * @see #test() * @see #test(Condition) * @see #uniqueIdSubstring(String) * @see #displayName(String) */ public static Condition test(String uniqueIdSubstring, String displayName) { return allOf(test(), uniqueIdSubstring(uniqueIdSubstring), displayName(displayName)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event} matches the supplied {@code Condition} and its * {@linkplain Event#getTestDescriptor() test descriptor} is a * {@linkplain TestDescriptor#isTest() test}. * *

For example, {@code test(displayName("my display name"))} can be used * to match against a test with the given display name. * * @since 1.8 * @see #test(String) * @see #test(String, String) * @see #displayName(String) */ @API(status = MAINTAINED, since = "1.8") public static Condition test(Condition condition) { return allOf(test(), condition); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isTest() test}. */ public static Condition test() { return new Condition<>(byTestDescriptor(TestDescriptor::isTest), "is a test"); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isContainer() container} and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the * fully-qualified name of the supplied {@link Class}. */ public static Condition container(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return container(clazz.getName()); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isContainer() container} and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the supplied * {@link String}. */ public static Condition container(String uniqueIdSubstring) { return container(uniqueIdSubstring(uniqueIdSubstring)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event} matches the supplied {@code Condition} and its * {@linkplain Event#getTestDescriptor() test descriptor} is a * {@linkplain TestDescriptor#isContainer() container}. */ public static Condition container(Condition condition) { return allOf(container(), condition); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isContainer() container}. */ public static Condition container() { return new Condition<>(byTestDescriptor(TestDescriptor::isContainer), "is a container"); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event} matches the supplied {@code Condition}, its * {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isContainer() container}, and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the * simple names of the supplied {@link Class} and all of its * {@linkplain Class#getEnclosingClass() enclosing classes}. * *

For example, {@code nestedContainer(MyNestedTests.class, displayName("my display name"))} * can be used to match against a nested container with the given display name. * *

Please note that this method does not differentiate between static * nested classes and non-static member classes (e.g., inner classes). * * @since 1.8 * @see #nestedContainer(Class) */ @API(status = MAINTAINED, since = "1.8") public static Condition nestedContainer(Class clazz, Condition condition) { return allOf(nestedContainer(clazz), condition); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} is * a {@linkplain TestDescriptor#isContainer() container} and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the * simple names of the supplied {@link Class} and all of its * {@linkplain Class#getEnclosingClass() enclosing classes}. * *

Please note that this method does not differentiate between static * nested classes and non-static member classes (e.g., inner classes). * * @see #nestedContainer(Class, Condition) */ public static Condition nestedContainer(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(clazz.getEnclosingClass(), () -> clazz.getName() + " must be a nested class"); List classNames = new ArrayList<>(); for (Class current = clazz; current != null; current = current.getEnclosingClass()) { classNames.add(0, current.getSimpleName()); } return allOf(container(), uniqueIdSubstrings(classNames)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#DYNAMIC_TEST_REGISTERED} and its * {@linkplain TestDescriptor#getUniqueId() unique id} contains the * supplied {@link String}. */ public static Condition dynamicTestRegistered(String uniqueIdSubstring) { return dynamicTestRegistered(uniqueIdSubstring(uniqueIdSubstring)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#DYNAMIC_TEST_REGISTERED} and it matches the supplied * {@code Condition}. */ public static Condition dynamicTestRegistered(Condition condition) { return allOf(type(DYNAMIC_TEST_REGISTERED), condition); } /** * Create a new {@link Condition} that matches if and only if the * {@linkplain TestDescriptor#getUniqueId() unique id} of an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} * contains the supplied {@link String}. */ public static Condition uniqueIdSubstring(String uniqueIdSubstring) { Predicate predicate = segment -> { String text = segment.getType() + ":" + segment.getValue(); return text.contains(uniqueIdSubstring); }; return new Condition<>( byTestDescriptor( where(TestDescriptor::getUniqueId, uniqueId -> uniqueId.getSegments().stream().anyMatch(predicate))), "descriptor with uniqueId substring '%s'", uniqueIdSubstring); } /** * Create a new {@link Condition} that matches if and only if the * {@linkplain TestDescriptor#getUniqueId() unique id} of an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} * contains all of the supplied strings. * * @since 1.6 */ public static Condition uniqueIdSubstrings(String... uniqueIdSubstrings) { return uniqueIdSubstrings(Arrays.asList(uniqueIdSubstrings)); } /** * Create a new {@link Condition} that matches if and only if the * {@linkplain TestDescriptor#getUniqueId() unique id} of an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} * contains all of the supplied strings. * * @since 1.6 */ public static Condition uniqueIdSubstrings(List uniqueIdSubstrings) { // The following worked with AssertJ 3.13.2 // return allOf(uniqueIdSubstrings.stream().map(EventConditions::uniqueIdSubstring).collect(toList())); // Workaround for a regression in AssertJ 3.14.0 that loses the individual descriptions // when multiple conditions are supplied as an Iterable instead of as an array. // The underlying cause is that org.assertj.core.condition.Join.Join(Condition...) // tracks all descriptions; whereas, // org.assertj.core.condition.Join.Join(Iterable>) // does not track all descriptions. List> conditions = uniqueIdSubstrings.stream()// .map(EventConditions::uniqueIdSubstring)// .collect(toList()); List descriptions = conditions.stream().map(Condition::description).collect(toList()); return allOf(conditions).describedAs(new JoinDescription("all of :[", "]", descriptions)); } /** * Create a new {@link Condition} that matches if and only if the * {@linkplain TestDescriptor#getDisplayName() display name} of an * {@link Event}'s {@linkplain Event#getTestDescriptor() test descriptor} * is equal to the supplied {@link String}. */ public static Condition displayName(String displayName) { return new Condition<>(byTestDescriptor(where(TestDescriptor::getDisplayName, isEqual(displayName))), "descriptor with display name '%s'", displayName); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#SKIPPED} and the * {@linkplain Event#getPayload() reason} is equal to the supplied * {@link String}. * * @see #reason(String) */ public static Condition skippedWithReason(String expectedReason) { return allOf(type(SKIPPED), reason(expectedReason)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#SKIPPED} and the * {@linkplain Event#getPayload() reason} matches the supplied * {@link Predicate}. * * @see #reason(Predicate) */ public static Condition skippedWithReason(Predicate predicate) { return allOf(type(SKIPPED), reason(predicate)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#STARTED}. */ public static Condition started() { return type(STARTED); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#FINISHED} and its * {@linkplain Event#getPayload() result} has a * {@linkplain TestExecutionResult#getStatus() status} of * {@link TestExecutionResult.Status#ABORTED ABORTED} as well as a * {@linkplain TestExecutionResult#getThrowable() cause} that matches all of * the supplied conditions. */ @SafeVarargs public static Condition abortedWithReason(Condition... conditions) { return finishedWithCause(ABORTED, conditions); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#FINISHED} and its * {@linkplain Event#getPayload() result} has a * {@linkplain TestExecutionResult#getStatus() status} of * {@link TestExecutionResult.Status#FAILED FAILED} as well as a * {@linkplain TestExecutionResult#getThrowable() cause} that matches all of * the supplied {@code Conditions}. */ @SafeVarargs public static Condition finishedWithFailure(Condition... conditions) { return finishedWithCause(FAILED, conditions); } @SuppressWarnings("unchecked") private static Condition finishedWithCause(Status expectedStatus, Condition... conditions) { List> list = Arrays.asList(TestExecutionResultConditions.status(expectedStatus), TestExecutionResultConditions.throwable(conditions)); return finished(allOf(list)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#FINISHED} and its * {@linkplain Event#getPayload() result} has a * {@linkplain TestExecutionResult#getStatus() status} of * {@link TestExecutionResult.Status#FAILED FAILED}. */ public static Condition finishedWithFailure() { return finished(TestExecutionResultConditions.status(FAILED)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#FINISHED} and its * {@linkplain Event#getPayload() result} has a * {@linkplain TestExecutionResult#getStatus() status} of * {@link TestExecutionResult.Status#SUCCESSFUL SUCCESSFUL}. */ public static Condition finishedSuccessfully() { return finished(TestExecutionResultConditions.status(SUCCESSFUL)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is * {@link EventType#FINISHED} and its * {@linkplain Event#getPayload() payload} is an instance of * {@link TestExecutionResult} that matches the supplied {@code Condition}. */ public static Condition finished(Condition resultCondition) { return allOf(type(FINISHED), result(resultCondition)); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getType() type} is equal to the * supplied {@link EventType}. */ public static Condition type(EventType expectedType) { return new Condition<>(byType(expectedType), "type is %s", expectedType); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getPayload() payload} is an instance of * {@link TestExecutionResult} that matches the supplied {@code Condition}. */ public static Condition result(Condition condition) { return new Condition<>(byPayload(TestExecutionResult.class, condition::matches), "event with result where %s", condition); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getPayload() payload} is an instance of * {@link String} that is equal to the supplied value. */ public static Condition reason(String expectedReason) { return new Condition<>(byPayload(String.class, isEqual(expectedReason)), "event with reason '%s'", expectedReason); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getPayload() payload} is an instance of * {@link String} that matches the supplied {@link Predicate}. */ public static Condition reason(Predicate predicate) { return new Condition<>(byPayload(String.class, predicate), "event with custom reason predicate"); } /** * Create a new {@link Condition} that matches if and only if an * {@link Event}'s {@linkplain Event#getPayload() payload} is an instance of * {@link ReportEntry} that contains the supplied key-value pairs. */ @API(status = STABLE, since = "1.10") public static Condition reportEntry(Map keyValuePairs) { return new Condition<>(byPayload(ReportEntry.class, it -> it.getKeyValuePairs().equals(keyValuePairs)), "event for report entry with key-value pairs %s", keyValuePairs); } } EventStatistics.java000066400000000000000000000105251455764576500347460ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.testkit.engine.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; import org.apiguardian.api.API; import org.junit.platform.testkit.engine.Assertions.Executable; /** * {@code EventStatistics} provides a fluent API for asserting statistics * for {@linkplain Event events}. * *

{@code EventStatistics} is used in conjunction with * {@link Events#assertStatistics(java.util.function.Consumer)} as in the * following example. * *

{@code events.assertStatistics(stats -> stats.started(1).succeeded(1).failed(0));} * * @since 1.4 * @see Event * @see Events */ @API(status = MAINTAINED, since = "1.7") public class EventStatistics { private final List executables = new ArrayList<>(); private final Events events; EventStatistics(Events events, String category) { this.events = events; } void assertAll() { Assertions.assertAll(this.events.getCategory() + " Event Statistics", this.executables.stream()); } // ------------------------------------------------------------------------- /** * Specify the number of expected skipped events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics skipped(long expected) { this.executables.add(() -> assertEquals(expected, this.events.skipped().count(), "skipped")); return this; } /** * Specify the number of expected started events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics started(long expected) { this.executables.add(() -> assertEquals(expected, this.events.started().count(), "started")); return this; } /** * Specify the number of expected finished events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics finished(long expected) { this.executables.add(() -> assertEquals(expected, this.events.finished().count(), "finished")); return this; } /** * Specify the number of expected aborted events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics aborted(long expected) { this.executables.add(() -> assertEquals(expected, this.events.aborted().count(), "aborted")); return this; } /** * Specify the number of expected succeeded events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics succeeded(long expected) { this.executables.add(() -> assertEquals(expected, this.events.succeeded().count(), "succeeded")); return this; } /** * Specify the number of expected failed events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics failed(long expected) { this.executables.add(() -> assertEquals(expected, this.events.failed().count(), "failed")); return this; } /** * Specify the number of expected reporting entry publication events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics reportingEntryPublished(long expected) { this.executables.add( () -> assertEquals(expected, this.events.reportingEntryPublished().count(), "reporting entry published")); return this; } /** * Specify the number of expected dynamic registration events. * * @param expected the expected number of events * @return this {@code EventStatistics} for method chaining */ public EventStatistics dynamicallyRegistered(long expected) { this.executables.add( () -> assertEquals(expected, this.events.dynamicallyRegistered().count(), "dynamically registered")); return this; } } junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventType.java000066400000000000000000000034741455764576500336210ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; /** * Enumeration of the different possible {@link Event} types. * * @since 1.4 * @see Event */ @API(status = MAINTAINED, since = "1.7") public enum EventType { /** * Signals that a {@link TestDescriptor} has been dynamically registered. * * @see org.junit.platform.engine.EngineExecutionListener#dynamicTestRegistered(TestDescriptor) */ DYNAMIC_TEST_REGISTERED, /** * Signals that the execution of a {@link TestDescriptor} has been skipped. * * @see org.junit.platform.engine.EngineExecutionListener#executionSkipped(TestDescriptor, String) */ SKIPPED, /** * Signals that the execution of a {@link TestDescriptor} has started. * * @see org.junit.platform.engine.EngineExecutionListener#executionStarted(TestDescriptor) */ STARTED, /** * Signals that the execution of a {@link TestDescriptor} has finished, * regardless of the outcome. * * @see org.junit.platform.engine.EngineExecutionListener#executionFinished(TestDescriptor, TestExecutionResult) */ FINISHED, /** * Signals that a {@link TestDescriptor} published a reporting entry. * * @see org.junit.platform.engine.EngineExecutionListener#reportingEntryPublished(TestDescriptor, ReportEntry) */ REPORTING_ENTRY_PUBLISHED; } junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Events.java000066400000000000000000000360051455764576500331360ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static java.util.Collections.sort; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.testkit.engine.Event.byPayload; import static org.junit.platform.testkit.engine.Event.byType; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import org.apiguardian.api.API; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; import org.assertj.core.api.ListAssert; import org.assertj.core.api.SoftAssertions; import org.assertj.core.data.Index; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; import org.opentest4j.AssertionFailedError; /** * {@code Events} is a facade that provides a fluent API for working with * {@linkplain Event events}. * * @since 1.4 */ @API(status = MAINTAINED, since = "1.7") public final class Events { private final List events; private final String category; Events(Stream events, String category) { this(Preconditions.notNull(events, "Event stream must not be null").collect(toList()), category); } Events(List events, String category) { Preconditions.notNull(events, "Event list must not be null"); Preconditions.containsNoNullElements(events, "Event list must not contain null elements"); this.events = Collections.unmodifiableList(events); this.category = category; } String getCategory() { return this.category; } // --- Accessors ----------------------------------------------------------- /** * Get the {@linkplain Event events} as a {@link List}. * * @return the list of events; never {@code null} * @see #stream() */ public List list() { return this.events; } /** * Get the {@linkplain Event events} as a {@link Stream}. * * @return the stream of events; never {@code null} * @see #list() */ public Stream stream() { return this.events.stream(); } /** * Shortcut for {@code events.stream().map(mapper)}. * * @param mapper a {@code Function} to apply to each event; never {@code null} * @return the mapped stream of events; never {@code null} * @see #stream() * @see Stream#map(Function) */ public Stream map(Function mapper) { Preconditions.notNull(mapper, "Mapping function must not be null"); return stream().map(mapper); } /** * Shortcut for {@code events.stream().filter(predicate)}. * * @param predicate a {@code Predicate} to apply to each event to decide if * it should be included in the filtered stream; never {@code null} * @return the filtered stream of events; never {@code null} * @see #stream() * @see Stream#filter(Predicate) */ public Stream filter(Predicate predicate) { Preconditions.notNull(predicate, "Filter predicate must not be null"); return stream().filter(predicate); } /** * Get the {@link Executions} for the current set of {@linkplain Event events}. * * @return an instance of {@code Executions} for the current set of events; * never {@code null} */ public Executions executions() { return new Executions(this.events, this.category); } // --- Statistics ---------------------------------------------------------- /** * Get the number of {@linkplain Event events} contained in this {@code Events} * object. */ public long count() { return this.events.size(); } // --- Built-in Filters ---------------------------------------------------- /** * Get the skipped {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events skipped() { return new Events(eventsByType(EventType.SKIPPED), this.category + " Skipped"); } /** * Get the started {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events started() { return new Events(eventsByType(EventType.STARTED), this.category + " Started"); } /** * Get the finished {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events finished() { return new Events(eventsByType(EventType.FINISHED), this.category + " Finished"); } /** * Get the aborted {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events aborted() { return new Events(finishedEventsByStatus(Status.ABORTED), this.category + " Aborted"); } /** * Get the succeeded {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events succeeded() { return new Events(finishedEventsByStatus(Status.SUCCESSFUL), this.category + " Successful"); } /** * Get the failed {@link Events} contained in this {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events failed() { return new Events(finishedEventsByStatus(Status.FAILED), this.category + " Failed"); } /** * Get the reporting entry publication {@link Events} contained in this * {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events reportingEntryPublished() { return new Events(eventsByType(EventType.REPORTING_ENTRY_PUBLISHED), this.category + " Reporting Entry Published"); } /** * Get the dynamic registration {@link Events} contained in this * {@code Events} object. * * @return the filtered {@code Events}; never {@code null} */ public Events dynamicallyRegistered() { return new Events(eventsByType(EventType.DYNAMIC_TEST_REGISTERED), this.category + " Dynamically Registered"); } // --- Assertions ---------------------------------------------------------- /** * Assert statistics for the {@linkplain Event events} contained in this * {@code Events} object. * *

Example

* *

{@code events.assertStatistics(stats -> stats.started(1).succeeded(1).failed(0));} * * @param statisticsConsumer a {@link Consumer} of {@link EventStatistics}; * never {@code null} * @return this {@code Events} object for method chaining; never {@code null} */ public Events assertStatistics(Consumer statisticsConsumer) { Preconditions.notNull(statisticsConsumer, "Consumer must not be null"); EventStatistics eventStatistics = new EventStatistics(this, this.category); statisticsConsumer.accept(eventStatistics); eventStatistics.assertAll(); return this; } /** * Assert that all {@linkplain Event events} contained in this {@code Events} * object exactly match the provided conditions. * *

Conditions can be imported statically from {@link EventConditions} * and {@link TestExecutionResultConditions}. * *

Example

* *
	 * executionResults.testEvents().assertEventsMatchExactly(
	 *     event(test("exampleTestMethod"), started()),
	 *     event(test("exampleTestMethod"), finishedSuccessfully())
	 * );
	 * 
* * @param conditions the conditions to match against; never {@code null} * @see #assertEventsMatchLoosely(Condition...) * @see #assertEventsMatchLooselyInOrder(Condition...) * @see EventConditions * @see TestExecutionResultConditions */ @SafeVarargs public final void assertEventsMatchExactly(Condition... conditions) { Preconditions.notNull(conditions, "conditions must not be null"); assertEventsMatchExactly(this.events, conditions); } /** * Assert that all provided conditions are matched by an {@linkplain Event event} * contained in this {@code Events} object, regardless of order. * *

Note that this method performs a partial match. Thus, some events may * not match any of the provided conditions. * *

Conditions can be imported statically from {@link EventConditions} * and {@link TestExecutionResultConditions}. * *

Example

* *
	 * executionResults.testEvents().assertEventsMatchLoosely(
	 *     event(test("exampleTestMethod"), started()),
	 *     event(test("exampleTestMethod"), finishedSuccessfully())
	 * );
	 * 
* * @param conditions the conditions to match against; never {@code null} * @since 1.7 * @see #assertEventsMatchExactly(Condition...) * @see #assertEventsMatchLooselyInOrder(Condition...) * @see EventConditions * @see TestExecutionResultConditions */ @SafeVarargs @SuppressWarnings("varargs") public final void assertEventsMatchLoosely(Condition... conditions) { Preconditions.notNull(conditions, "conditions must not be null"); Preconditions.containsNoNullElements(conditions, "conditions must not contain null elements"); assertEventsMatchLoosely(this.events, conditions); } /** * Assert that all provided conditions are matched by an {@linkplain Event event} * contained in this {@code Events} object. * *

Note that this method performs a partial match. Thus, some events may * not match any of the provided conditions; however, the conditions provided * must be in the correct order. * *

Conditions can be imported statically from {@link EventConditions} * and {@link TestExecutionResultConditions}. * *

Example

* *
	 * executionResults.testEvents().assertEventsMatchLooselyInOrder(
	 *     event(test("exampleTestMethod"), started()),
	 *     event(test("exampleTestMethod"), finishedSuccessfully())
	 * );
	 * 
* * @param conditions the conditions to match against; never {@code null} * @since 1.7 * @see #assertEventsMatchExactly(Condition...) * @see #assertEventsMatchLoosely(Condition...) * @see EventConditions * @see TestExecutionResultConditions */ @SafeVarargs @SuppressWarnings("varargs") public final void assertEventsMatchLooselyInOrder(Condition... conditions) { Preconditions.notNull(conditions, "conditions must not be null"); Preconditions.containsNoNullElements(conditions, "conditions must not contain null elements"); assertEventsMatchLooselyInOrder(this.events, conditions); } /** * Shortcut for {@code org.assertj.core.api.Assertions.assertThat(events.list())}. * * @return an instance of {@link ListAssert} for events; never {@code null} * @see org.assertj.core.api.Assertions#assertThat(List) * @see org.assertj.core.api.ListAssert */ public ListAssert assertThatEvents() { return org.assertj.core.api.Assertions.assertThat(list()); } // --- Diagnostics --------------------------------------------------------- /** * Print all events to {@link System#out}. * * @return this {@code Events} object for method chaining; never {@code null} */ public Events debug() { debug(System.out); return this; } /** * Print all events to the supplied {@link OutputStream}. * * @param out the {@code OutputStream} to print to; never {@code null} * @return this {@code Events} object for method chaining; never {@code null} */ public Events debug(OutputStream out) { Preconditions.notNull(out, "OutputStream must not be null"); debug(new PrintWriter(out, true)); return this; } /** * Print all events to the supplied {@link Writer}. * * @param writer the {@code Writer} to print to; never {@code null} * @return this {@code Events} object for method chaining; never {@code null} */ public Events debug(Writer writer) { Preconditions.notNull(writer, "Writer must not be null"); debug(new PrintWriter(writer, true)); return this; } private Events debug(PrintWriter printWriter) { printWriter.println(this.category + " Events:"); this.events.forEach(event -> printWriter.printf("\t%s%n", event)); return this; } // --- Internals ----------------------------------------------------------- private Stream eventsByType(EventType type) { Preconditions.notNull(type, "EventType must not be null"); return stream().filter(byType(type)); } private Stream finishedEventsByStatus(Status status) { Preconditions.notNull(status, "Status must not be null"); return eventsByType(EventType.FINISHED)// .filter(byPayload(TestExecutionResult.class, where(TestExecutionResult::getStatus, isEqual(status)))); } @SafeVarargs private static void assertEventsMatchExactly(List events, Condition... conditions) { Assertions.assertThat(events).hasSize(conditions.length); SoftAssertions softly = new SoftAssertions(); for (int i = 0; i < conditions.length; i++) { softly.assertThat(events).has(conditions[i], Index.atIndex(i)); } softly.assertAll(); } @SafeVarargs private static void assertEventsMatchLoosely(List events, Condition... conditions) { SoftAssertions softly = new SoftAssertions(); for (Condition condition : conditions) { checkCondition(events, softly, condition); } softly.assertAll(); } @SafeVarargs @SuppressWarnings("varargs") private static void assertEventsMatchLooselyInOrder(List events, Condition... conditions) { Assertions.assertThat(conditions).hasSizeLessThanOrEqualTo(events.size()); SoftAssertions softly = new SoftAssertions(); // @formatter:off List indices = Arrays.stream(conditions) .map(condition -> findEvent(events, softly, condition)) .filter(Objects::nonNull) .map(events::indexOf) .collect(toList()); // @formatter:on if (isNotInIncreasingOrder(indices)) { throw new AssertionFailedError("Conditions are not in the correct order."); } softly.assertAll(); } private static boolean isNotInIncreasingOrder(List indices) { List copy = new ArrayList<>(indices); sort(copy); return !indices.equals(copy); } private static void checkCondition(List events, SoftAssertions softly, Condition condition) { if (events.stream().noneMatch(condition::matches)) { softly.fail("Condition did not match any event: " + condition); } } private static Event findEvent(List events, SoftAssertions softly, Condition condition) { // @formatter:off Optional matchedEvent = events.stream() .filter(condition::matches) .findFirst(); // @formatter:on if (!matchedEvent.isPresent()) { softly.fail("Condition did not match any event: " + condition); } return matchedEvent.orElse(null); } } junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Execution.java000066400000000000000000000116661455764576500336430ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import java.time.Duration; import java.time.Instant; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; /** * {@code Execution} encapsulates metadata for the execution of a single * {@link TestDescriptor}. * * @since 1.4 */ @API(status = MAINTAINED, since = "1.7") public class Execution { // --- Factories ----------------------------------------------------------- /** * Create a new instance of an {@code Execution} that finished with the * provided {@link TestExecutionResult}. * * @param testDescriptor the {@code TestDescriptor} that finished; * never {@code null} * @param startInstant the {@code Instant} that the {@code Execution} started; * never {@code null} * @param endInstant the {@code Instant} that the {@code Execution} completed; * never {@code null} * @param executionResult the {@code TestExecutionResult} of the finished * {@code TestDescriptor}; never {@code null} * @return the newly created {@code Execution} instance; never {@code null} */ public static Execution finished(TestDescriptor testDescriptor, Instant startInstant, Instant endInstant, TestExecutionResult executionResult) { return new Execution(testDescriptor, startInstant, endInstant, TerminationInfo.executed(executionResult)); } /** * Create a new instance of an {@code Execution} that was skipped with the * provided {@code skipReason}. * * @param testDescriptor the {@code TestDescriptor} that finished; * never {@code null} * @param startInstant the {@code Instant} that the {@code Execution} started; * never {@code null} * @param endInstant the {@code Instant} that the {@code Execution} completed; * never {@code null} * @param skipReason the reason the {@code TestDescriptor} was skipped; * may be {@code null} * @return the newly created {@code Execution} instance; never {@code null} */ public static Execution skipped(TestDescriptor testDescriptor, Instant startInstant, Instant endInstant, String skipReason) { return new Execution(testDescriptor, startInstant, endInstant, TerminationInfo.skipped(skipReason)); } // ------------------------------------------------------------------------- private final TestDescriptor testDescriptor; private final Instant startInstant; private final Instant endInstant; private final Duration duration; private final TerminationInfo terminationInfo; private Execution(TestDescriptor testDescriptor, Instant startInstant, Instant endInstant, TerminationInfo terminationInfo) { Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); Preconditions.notNull(startInstant, "Start Instant must not be null"); Preconditions.notNull(endInstant, "End Instant must not be null"); Preconditions.notNull(terminationInfo, "TerminationInfo must not be null"); this.testDescriptor = testDescriptor; this.startInstant = startInstant; this.endInstant = endInstant; this.duration = Duration.between(startInstant, endInstant); this.terminationInfo = terminationInfo; } /** * Get the {@link TestDescriptor} for this {@code Execution}. * * @return the {@code TestDescriptor} for this {@code Execution} */ public TestDescriptor getTestDescriptor() { return this.testDescriptor; } /** * Get the start {@link Instant} of this {@code Execution}. * * @return the start {@code Instant} of this {@code Execution} */ public Instant getStartInstant() { return this.startInstant; } /** * Get the end {@link Instant} of this {@code Execution}. * * @return the end {@code Instant} of this {@code Execution} */ public Instant getEndInstant() { return this.endInstant; } /** * Get the {@link Duration} of this {@code Execution}. * * @return the {@code Duration} of this {@code Execution} */ public Duration getDuration() { return this.duration; } /** * Get the {@link TerminationInfo} for this {@code Execution}. * * @return the {@code TerminationInfo} for this {@code Execution} */ public TerminationInfo getTerminationInfo() { return this.terminationInfo; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("testDescriptor", this.testDescriptor) .append("startInstant", this.startInstant) .append("endInstant", this.endInstant) .append("duration", this.duration) .append("terminationInfo", this.terminationInfo) .toString(); // @formatter:on } } ExecutionRecorder.java000066400000000000000000000054661455764576500352530ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.apiguardian.api.API; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; /** * {@code ExecutionRecorder} is an {@link EngineExecutionListener} that records * data from every event that occurs during the engine execution lifecycle and * provides functionality for retrieving execution state via * {@link EngineExecutionResults}. * * @since 1.4 * @see EngineExecutionResults * @see Event * @see Execution */ @API(status = MAINTAINED, since = "1.7") public class ExecutionRecorder implements EngineExecutionListener { private final List events = new CopyOnWriteArrayList<>(); public ExecutionRecorder() { } /** * Record an {@link Event} for a dynamically registered container * or test. */ @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { this.events.add(Event.dynamicTestRegistered(testDescriptor)); } /** * Record an {@link Event} for a container or test that was skipped. */ @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { this.events.add(Event.executionSkipped(testDescriptor, reason)); } /** * Record an {@link Event} for a container or test that started. */ @Override public void executionStarted(TestDescriptor testDescriptor) { this.events.add(Event.executionStarted(testDescriptor)); } /** * Record an {@link Event} for a container or test that completed * with the provided {@link TestExecutionResult}. */ @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { this.events.add(Event.executionFinished(testDescriptor, testExecutionResult)); } /** * Record an {@link Event} for a published {@link ReportEntry}. */ @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { this.events.add(Event.reportingEntryPublished(testDescriptor, entry)); } /** * Get the state of the engine's execution in the form of {@link EngineExecutionResults}. * * @return the {@code EngineExecutionResults} containing all current state information */ public EngineExecutionResults getExecutionResults() { return new EngineExecutionResults(this.events); } } Executions.java000066400000000000000000000231371455764576500337430ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import org.apiguardian.api.API; import org.assertj.core.api.ListAssert; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; /** * {@code Executions} is a facade that provides a fluent API for working with * {@linkplain Execution executions}. * * @since 1.4 */ @API(status = MAINTAINED, since = "1.7") public final class Executions { private final List executions; private final String category; private Executions(Stream executions, String category) { Preconditions.notNull(executions, "Execution stream must not be null"); this.executions = Collections.unmodifiableList(executions.collect(toList())); this.category = category; } Executions(List events, String category) { Preconditions.notNull(events, "Event list must not be null"); Preconditions.containsNoNullElements(events, "Event list must not contain null elements"); this.executions = Collections.unmodifiableList(createExecutions(events)); this.category = category; } // --- Accessors ----------------------------------------------------------- /** * Get the {@linkplain Execution executions} as a {@link List}. * * @return the list of executions; never {@code null} * @see #stream() */ public List list() { return this.executions; } /** * Get the {@linkplain Execution executions} as a {@link Stream}. * * @return the stream of executions; never {@code null} * @see #list() */ public Stream stream() { return this.executions.stream(); } /** * Shortcut for {@code executions.stream().map(mapper)}. * * @param mapper a {@code Function} to apply to each execution; * never {@code null} * @return the mapped stream of executions; never {@code null} * @see #stream() * @see Stream#map(Function) */ public Stream map(Function mapper) { Preconditions.notNull(mapper, "Mapping function must not be null"); return stream().map(mapper); } /** * Shortcut for {@code executions.stream().filter(predicate)}. * * @param predicate a {@code Predicate} to apply to each execution to decide * if it should be included in the filtered stream; never {@code null} * @return the filtered stream of executions; never {@code null} * @see #stream() * @see Stream#filter(Predicate) */ public Stream filter(Predicate predicate) { Preconditions.notNull(predicate, "Filter predicate must not be null"); return stream().filter(predicate); } // --- Statistics ---------------------------------------------------------- /** * Get the number of {@linkplain Execution executions} contained in this * {@code Executions} object. */ public long count() { return this.executions.size(); } // --- Built-in Filters ---------------------------------------------------- /** * Get the skipped {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions skipped() { return new Executions(executionsByTerminationInfo(TerminationInfo::skipped), this.category + " Skipped"); } /** * Get the started {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions started() { return new Executions(executionsByTerminationInfo(TerminationInfo::notSkipped), this.category + " Started"); } /** * Get the finished {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions finished() { return new Executions(finishedExecutions(), this.category + " Finished"); } /** * Get the aborted {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions aborted() { return new Executions(finishedExecutionsByStatus(Status.ABORTED), this.category + " Aborted"); } /** * Get the succeeded {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions succeeded() { return new Executions(finishedExecutionsByStatus(Status.SUCCESSFUL), this.category + " Successful"); } /** * Get the failed {@link Executions} contained in this {@code Executions} object. * * @return the filtered {@code Executions}; never {@code null} */ public Executions failed() { return new Executions(finishedExecutionsByStatus(Status.FAILED), this.category + " Failed"); } // --- Assertions ---------------------------------------------------------- /** * Shortcut for {@code org.assertj.core.api.Assertions.assertThat(executions.list())}. * * @return an instance of {@link ListAssert} for executions; never {@code null} * @see org.assertj.core.api.Assertions#assertThat(List) * @see org.assertj.core.api.ListAssert */ public ListAssert assertThatExecutions() { return org.assertj.core.api.Assertions.assertThat(list()); } // --- Diagnostics --------------------------------------------------------- /** * Print all executions to {@link System#out}. * * @return this {@code Executions} object for method chaining; never {@code null} */ public Executions debug() { debug(System.out); return this; } /** * Print all executions to the supplied {@link OutputStream}. * * @param out the {@code OutputStream} to print to; never {@code null} * @return this {@code Executions} object for method chaining; never {@code null} */ public Executions debug(OutputStream out) { Preconditions.notNull(out, "OutputStream must not be null"); debug(new PrintWriter(out, true)); return this; } /** * Print all executions to the supplied {@link Writer}. * * @param writer the {@code Writer} to print to; never {@code null} * @return this {@code Executions} object for method chaining; never {@code null} */ public Executions debug(Writer writer) { Preconditions.notNull(writer, "Writer must not be null"); debug(new PrintWriter(writer, true)); return this; } private Executions debug(PrintWriter printWriter) { printWriter.println(this.category + " Executions:"); this.executions.forEach(execution -> printWriter.printf("\t%s%n", execution)); return this; } // --- Internals ----------------------------------------------------------- private Stream finishedExecutions() { return executionsByTerminationInfo(TerminationInfo::executed); } private Stream finishedExecutionsByStatus(Status status) { Preconditions.notNull(status, "Status must not be null"); return finishedExecutions()// .filter(execution -> execution.getTerminationInfo().getExecutionResult().getStatus() == status); } private Stream executionsByTerminationInfo(Predicate predicate) { return filter(execution -> predicate.test(execution.getTerminationInfo())); } /** * Create executions from the supplied list of events. */ private static List createExecutions(List events) { List executions = new ArrayList<>(); Map executionStarts = new HashMap<>(); for (Event event : events) { switch (event.getType()) { case STARTED: { executionStarts.put(event.getTestDescriptor(), event.getTimestamp()); break; } case SKIPPED: { // Based on the Javadoc for EngineExecutionListener.executionSkipped(...), // a skipped descriptor must never be reported as started or finished, // but just in case a TestEngine does not adhere to that contract, we // make an attempt to remove any tracked "started" event. executionStarts.remove(event.getTestDescriptor()); // Use the same timestamp for both the start and end Instant values. Instant timestamp = event.getTimestamp(); Execution skippedEvent = Execution.skipped(event.getTestDescriptor(), timestamp, timestamp, event.getRequiredPayload(String.class)); executions.add(skippedEvent); break; } case FINISHED: { Instant startInstant = executionStarts.remove(event.getTestDescriptor()); Instant endInstant = event.getTimestamp(); // If "started" events have already been filtered out, it is no // longer possible to create a legitimate Execution for the current // descriptor. So we effectively ignore it in that case. if (startInstant != null) { Execution finishedEvent = Execution.finished(event.getTestDescriptor(), startInstant, endInstant, event.getRequiredPayload(TestExecutionResult.class)); executions.add(finishedEvent); } break; } default: { // Ignore other events break; } } } return executions; } } TerminationInfo.java000066400000000000000000000111461455764576500347170ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestExecutionResult; /** * {@code TerminationInfo} is a union type that allows propagation of terminated * container/test state, supporting either the reason if the container/test * was skipped or the {@link TestExecutionResult} if the container/test was executed. * * @since 1.4 * @see Execution#getTerminationInfo() */ @API(status = MAINTAINED, since = "1.7") public class TerminationInfo { // --- Factories ----------------------------------------------------------- /** * Create a skipped {@code TerminationInfo} instance for the * supplied reason. * * @param reason the reason the execution was skipped; may be {@code null} * @return the created {@code TerminationInfo}; never {@code null} * @see #executed(TestExecutionResult) */ public static TerminationInfo skipped(String reason) { return new TerminationInfo(true, reason, null); } /** * Create an executed {@code TerminationInfo} instance for the * supplied {@link TestExecutionResult}. * * @param testExecutionResult the result of the execution; never {@code null} * @return the created {@code TerminationInfo}; never {@code null} * @see #skipped(String) */ public static TerminationInfo executed(TestExecutionResult testExecutionResult) { Preconditions.notNull(testExecutionResult, "TestExecutionResult must not be null"); return new TerminationInfo(false, null, testExecutionResult); } // ------------------------------------------------------------------------- private final boolean skipped; private final String skipReason; private final TestExecutionResult testExecutionResult; private TerminationInfo(boolean skipped, String skipReason, TestExecutionResult testExecutionResult) { boolean executed = (testExecutionResult != null); Preconditions.condition((skipped ^ executed), "TerminationInfo must represent either a skipped execution or a TestExecutionResult but not both"); this.skipped = skipped; this.skipReason = skipReason; this.testExecutionResult = testExecutionResult; } /** * Determine if this {@code TerminationInfo} represents a skipped execution. * * @return {@code true} if this this {@code TerminationInfo} represents a * skipped execution */ public boolean skipped() { return this.skipped; } /** * Determine if this {@code TerminationInfo} does not represent a skipped * execution. * * @return {@code true} if this this {@code TerminationInfo} does not * represent a skipped execution */ public boolean notSkipped() { return !skipped(); } /** * Determine if this {@code TerminationInfo} represents a completed execution. * * @return {@code true} if this this {@code TerminationInfo} represents a * completed execution */ public boolean executed() { return (this.testExecutionResult != null); } /** * Get the reason the execution was skipped. * * @return the reason the execution was skipped * @throws UnsupportedOperationException if this {@code TerminationInfo} * does not represent a skipped execution */ public String getSkipReason() throws UnsupportedOperationException { if (skipped()) { return this.skipReason; } // else throw new UnsupportedOperationException("No skip reason contained in this TerminationInfo"); } /** * Get the {@link TestExecutionResult} for the completed execution. * * @return the result of the completed execution * @throws UnsupportedOperationException if this {@code TerminationInfo} * does not represent a completed execution */ public TestExecutionResult getExecutionResult() throws UnsupportedOperationException { if (executed()) { return this.testExecutionResult; } // else throw new UnsupportedOperationException("No TestExecutionResult contained in this TerminationInfo"); } @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); if (skipped()) { builder.append("skipped", true).append("reason", this.skipReason); } else { builder.append("executed", true).append("result", this.testExecutionResult); } return builder.toString(); } } TestExecutionResultConditions.java000066400000000000000000000120011455764576500376350ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import org.apiguardian.api.API; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; /** * Collection of AssertJ {@linkplain Condition conditions} for * {@link TestExecutionResult}. * * @since 1.4 * @see EventConditions */ @API(status = MAINTAINED, since = "1.7") public final class TestExecutionResultConditions { private TestExecutionResultConditions() { /* no-op */ } /** * Create a new {@link Condition} that matches if and only if a * {@link TestExecutionResult}'s {@linkplain TestExecutionResult#getStatus() * status} is equal to the supplied {@link Status Status}. */ public static Condition status(Status expectedStatus) { return new Condition<>(where(TestExecutionResult::getStatus, isEqual(expectedStatus)), "status is %s", expectedStatus); } /** * Create a new {@link Condition} that matches if and only if a * {@link TestExecutionResult}'s * {@linkplain TestExecutionResult#getThrowable() throwable} matches all * supplied conditions. */ @SafeVarargs @SuppressWarnings("varargs") public static Condition throwable(Condition... conditions) { List> list = Arrays.stream(conditions)// .map(TestExecutionResultConditions::throwable)// .collect(toList()); return Assertions.allOf(list); } /** * Create a new {@link Condition} that matches if and only if a * {@link Throwable}'s {@linkplain Throwable#getCause() cause} matches all * supplied conditions. */ @SafeVarargs @SuppressWarnings("varargs") public static Condition cause(Condition... conditions) { List> list = Arrays.stream(conditions)// .map(TestExecutionResultConditions::cause)// .collect(toList()); return Assertions.allOf(list); } /** * Create a new {@link Condition} that matches if and only if a * {@link Throwable}'s {@linkplain Throwable#getSuppressed() suppressed * throwable} at the supplied index matches all supplied conditions. */ @SafeVarargs @SuppressWarnings("varargs") public static Condition suppressed(int index, Condition... conditions) { List> list = Arrays.stream(conditions)// .map(condition -> suppressed(index, condition))// .collect(toList()); return Assertions.allOf(list); } /** * Create a new {@link Condition} that matches if and only if a * {@link Throwable} is an {@linkplain Class#isInstance(Object) instance of} * the supplied {@link Class}. */ public static Condition instanceOf(Class expectedType) { return new Condition<>(expectedType::isInstance, "instance of %s", expectedType.getName()); } /** * Create a new {@link Condition} that matches if and only if a * {@link Throwable}'s {@linkplain Throwable#getMessage() message} is equal * to the supplied {@link String}. */ public static Condition message(String expectedMessage) { return new Condition<>(where(Throwable::getMessage, isEqual(expectedMessage)), "message is '%s'", expectedMessage); } /** * Create a new {@link Condition} that matches if and only if a * {@link Throwable}'s {@linkplain Throwable#getMessage() message} matches * the supplied {@link Predicate}. */ public static Condition message(Predicate expectedMessagePredicate) { return new Condition<>(where(Throwable::getMessage, expectedMessagePredicate), "message matches predicate"); } private static Condition throwable(Condition condition) { return new Condition<>( where(TestExecutionResult::getThrowable, throwable -> throwable.isPresent() && condition.matches(throwable.get())), "throwable matches %s", condition); } private static Condition cause(Condition condition) { return new Condition<>(throwable -> condition.matches(throwable.getCause()), "throwable cause matches %s", condition); } private static Condition suppressed(int index, Condition condition) { return new Condition<>( throwable -> throwable.getSuppressed().length > index && condition.matches(throwable.getSuppressed()[index]), "suppressed throwable at index %d matches %s", index, condition); } } package-info.java000066400000000000000000000002561455764576500341360ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/** * Test Kit for testing the execution of a {@link org.junit.platform.engine.TestEngine} * running on the JUnit Platform. */ package org.junit.platform.testkit.engine; junit5-r5.10.2/junit-platform-testkit/src/main/java/org/junit/platform/testkit/package-info.java000066400000000000000000000001211455764576500327370ustar00rootroot00000000000000/** * Test Kit for the JUnit Platform. */ package org.junit.platform.testkit; junit5-r5.10.2/junit-platform-testkit/src/module/000077500000000000000000000000001455764576500217435ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/module/org.junit.platform.testkit/000077500000000000000000000000001455764576500271735ustar00rootroot00000000000000junit5-r5.10.2/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java000066400000000000000000000015611455764576500322570ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Defines the Test Kit API for the JUnit Platform. * * @since 1.4 * @uses org.junit.platform.engine.TestEngine */ module org.junit.platform.testkit { requires static transitive org.apiguardian.api; requires transitive org.assertj.core; requires org.junit.platform.commons; requires transitive org.junit.platform.engine; requires transitive org.junit.platform.launcher; requires transitive org.opentest4j; // exports org.junit.platform.testkit; empty package exports org.junit.platform.testkit.engine; uses org.junit.platform.engine.TestEngine; } junit5-r5.10.2/junit-vintage-engine/000077500000000000000000000000001455764576500172565ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/junit-vintage-engine.gradle.kts000066400000000000000000000055511455764576500252730ustar00rootroot00000000000000plugins { id("junitbuild.java-library-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") `java-test-fixtures` groovy } description = "JUnit Vintage Engine" dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformEngine) api(libs.junit4) compileOnlyApi(libs.apiguardian) testFixturesApi(platform(libs.groovy2.bom)) testFixturesApi(libs.spock1) testFixturesImplementation(projects.junitPlatformRunner) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(projects.junitPlatformTestkit) testImplementation(testFixtures(projects.junitJupiterApi)) osgiVerification(projects.junitPlatformLauncher) } tasks { compileTestFixturesGroovy { javaLauncher = project.javaToolchains.launcherFor { // Groovy 2.x (used for Spock tests) does not support current JDKs languageVersion = JavaLanguageVersion.of(8) } } jar { bundle { val junit4Min = libs.versions.junit4Min.get() val platformVersion: String by rootProject.extra val version = project.version bnd(""" # Import JUnit4 packages with a version Import-Package: \ ${extra["importAPIGuardian"]},\ junit.runner;version="[${junit4Min},5)",\ org.junit;version="[${junit4Min},5)",\ org.junit.experimental.categories;version="[${junit4Min},5)",\ org.junit.internal.builders;version="[${junit4Min},5)",\ org.junit.platform.commons.logging;status=INTERNAL,\ org.junit.runner.*;version="[${junit4Min},5)",\ org.junit.runners.model;version="[${junit4Min},5)",\ * Provide-Capability:\ org.junit.platform.engine;\ org.junit.platform.engine='junit-vintage';\ version:Version="${'$'}{version_cleanup;$version}" Require-Capability:\ org.junit.platform.launcher;\ filter:='(&(org.junit.platform.launcher=junit-platform-launcher)(version>=${'$'}{version_cleanup;$platformVersion})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;$platformVersion}})))';\ effective:=active """) } } val testWithoutJUnit4 by registering(Test::class) { val test by testing.suites.existing(JvmTestSuite::class) (options as JUnitPlatformOptions).apply { includeTags("missing-junit4") } setIncludes(listOf("**/JUnit4VersionCheckTests.class")) testClassesDirs = files(test.map { it.sources.output.classesDirs }) classpath = files(test.map { it.sources.runtimeClasspath }).filter { !it.name.startsWith("junit-4") } } withType().matching { it.name != testWithoutJUnit4.name }.configureEach { (options as JUnitPlatformOptions).apply { excludeTags("missing-junit4") } } withType().configureEach { // Workaround for Groovy 2.5 jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.util=ALL-UNNAMED") } check { dependsOn(testWithoutJUnit4) } } junit5-r5.10.2/junit-vintage-engine/src/000077500000000000000000000000001455764576500200455ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/000077500000000000000000000000001455764576500207715ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/000077500000000000000000000000001455764576500217125ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/000077500000000000000000000000001455764576500225015ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/000077500000000000000000000000001455764576500236325ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/000077500000000000000000000000001455764576500252675ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/000077500000000000000000000000001455764576500265345ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/JUnit4VersionCheck.java000066400000000000000000000045071455764576500330260ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID; import java.math.BigDecimal; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import junit.runner.Version; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * @since 5.4 */ class JUnit4VersionCheck { private static final Pattern versionPattern = Pattern.compile("^(\\d+\\.\\d+).*"); private static final BigDecimal minVersion = new BigDecimal("4.12"); static void checkSupported() { try { checkSupported(Version::id); } catch (NoClassDefFoundError e) { throw new JUnitException( "Invalid class/module path: junit-vintage-engine is present but junit:junit is not. " + "Please either remove junit-vintage-engine or add junit:junit, or " + "alternatively use an excludeEngines(\"" + ENGINE_ID + "\") filter."); } } static void checkSupported(Supplier versionSupplier) { String versionString = readVersion(versionSupplier); BigDecimal version = parseVersion(versionString); if (version.compareTo(minVersion) < 0) { throw new JUnitException("Unsupported version of junit:junit: " + versionString + ". Please upgrade to version " + minVersion + " or later."); } } static BigDecimal parseVersion(String versionString) { try { Matcher matcher = versionPattern.matcher(versionString); if (matcher.matches()) { return new BigDecimal(matcher.group(1)); } } catch (Exception e) { throw new JUnitException("Failed to parse version of junit:junit: " + versionString, e); } throw new JUnitException("Failed to parse version of junit:junit: " + versionString); } private static String readVersion(Supplier versionSupplier) { try { return versionSupplier.get(); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); throw new JUnitException("Failed to read version of junit:junit", t); } } } junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/VintageTestEngine.java000066400000000000000000000054761455764576500327760ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID; import java.util.Iterator; import java.util.Optional; import org.apiguardian.api.API; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageEngineDescriptor; import org.junit.vintage.engine.discovery.VintageDiscoverer; import org.junit.vintage.engine.execution.RunnerExecutor; /** * The JUnit Vintage {@link TestEngine}. * * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public final class VintageTestEngine implements TestEngine { @Override public String getId() { return ENGINE_ID; } /** * Returns {@code org.junit.vintage} as the group ID. */ @Override public Optional getGroupId() { return Optional.of("org.junit.vintage"); } /** * Returns {@code junit-vintage-engine} as the artifact ID. */ @Override public Optional getArtifactId() { return Optional.of("junit-vintage-engine"); } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { JUnit4VersionCheck.checkSupported(); return new VintageDiscoverer().discover(discoveryRequest, uniqueId); } @Override public void execute(ExecutionRequest request) { EngineExecutionListener engineExecutionListener = request.getEngineExecutionListener(); VintageEngineDescriptor engineDescriptor = (VintageEngineDescriptor) request.getRootTestDescriptor(); engineExecutionListener.executionStarted(engineDescriptor); executeAllChildren(engineDescriptor, engineExecutionListener); engineExecutionListener.executionFinished(engineDescriptor, successful()); } private void executeAllChildren(VintageEngineDescriptor engineDescriptor, EngineExecutionListener engineExecutionListener) { RunnerExecutor runnerExecutor = new RunnerExecutor(engineExecutionListener); for (Iterator iterator = engineDescriptor.getModifiableChildren().iterator(); iterator.hasNext();) { runnerExecutor.execute((RunnerTestDescriptor) iterator.next()); iterator.remove(); } } } junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/000077500000000000000000000000001455764576500307125ustar00rootroot00000000000000DescriptionUtils.java000066400000000000000000000017071455764576500350070ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import org.apiguardian.api.API; import org.junit.runner.Description; @API(status = API.Status.INTERNAL, since = "5.8") public class DescriptionUtils { private DescriptionUtils() { } public static String getMethodName(Description description) { String displayName = description.getDisplayName(); int i = displayName.indexOf('('); if (i >= 0) { int j = displayName.lastIndexOf('('); if (i == j) { char lastChar = displayName.charAt(displayName.length() - 1); if (lastChar == ')') { return displayName.substring(0, i); } } } return description.getMethodName(); } } junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/OrFilter.java000066400000000000000000000020761455764576500333100ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static java.util.stream.Collectors.joining; import java.util.Collection; import org.junit.platform.commons.util.Preconditions; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; /** * @since 5.4 */ class OrFilter extends Filter { private final Collection filters; OrFilter(Collection filters) { this.filters = Preconditions.notEmpty(filters, "filters must not be empty"); } @Override public boolean shouldRun(Description description) { return filters.stream().anyMatch(filter -> filter.shouldRun(description)); } @Override public String describe() { return filters.stream().map(Filter::describe).collect(joining(" OR ")); } } RunnerDecorator.java000066400000000000000000000011161455764576500346110ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.runner.Runner; @API(status = INTERNAL, since = "5.4") public interface RunnerDecorator { Runner getDecoratedRunner(); } RunnerRequest.java000066400000000000000000000012021455764576500343130ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import org.junit.runner.Request; import org.junit.runner.Runner; /** * @since 4.12 */ class RunnerRequest extends Request { private final Runner runner; RunnerRequest(Runner runner) { this.runner = runner; } @Override public Runner getRunner() { return runner; } } RunnerTestDescriptor.java000066400000000000000000000124771455764576500356610ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static java.util.Collections.singletonList; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.runner.Description; import org.junit.runner.Request; import org.junit.runner.Runner; import org.junit.runner.manipulation.Filter; import org.junit.runner.manipulation.Filterable; import org.junit.runner.manipulation.NoTestsRemainException; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class RunnerTestDescriptor extends VintageTestDescriptor { private static final Logger logger = LoggerFactory.getLogger(RunnerTestDescriptor.class); private final Set rejectedExclusions = new HashSet<>(); private Runner runner; private final boolean ignored; private boolean wasFiltered; private List filters = new ArrayList<>(); public RunnerTestDescriptor(UniqueId uniqueId, Class testClass, Runner runner, boolean ignored) { super(uniqueId, runner.getDescription(), testClass.getSimpleName(), ClassSource.from(testClass)); this.runner = runner; this.ignored = ignored; } @Override public String getLegacyReportingName() { return getSource().map(source -> ((ClassSource) source).getClassName()) // .orElseThrow(() -> new JUnitException("source should have been present")); } public Request toRequest() { return new RunnerRequest(this.runner); } @Override protected boolean tryToExcludeFromRunner(Description description) { boolean excluded = tryToFilterRunner(description); if (excluded) { wasFiltered = true; } else { rejectedExclusions.add(description); } return excluded; } private boolean tryToFilterRunner(Description description) { if (runner instanceof Filterable) { ExcludeDescriptionFilter filter = new ExcludeDescriptionFilter(description); try { ((Filterable) runner).filter(filter); } catch (NoTestsRemainException ignore) { // it's safe to ignore this exception because childless TestDescriptors will get pruned } return filter.wasSuccessful(); } return false; } @Override protected boolean canBeRemovedFromHierarchy() { return true; } @Override public void prune() { if (wasFiltered) { // filtering the runner may render intermediate Descriptions obsolete // (e.g. test classes without any remaining children in a suite) pruneDescriptorsForObsoleteDescriptions(singletonList(runner.getDescription())); } if (rejectedExclusions.isEmpty()) { super.prune(); } else if (rejectedExclusions.containsAll(getDescription().getChildren())) { // since the Runner was asked to remove all of its direct children, // it's safe to remove it entirely removeFromHierarchy(); } else { logIncompleteFiltering(); } } private void logIncompleteFiltering() { if (runner instanceof Filterable) { logger.warn(() -> "Runner " + getRunnerToReport().getClass().getName() // + " (used on class " + getLegacyReportingName() + ") was not able to satisfy all filter requests."); } else { warnAboutUnfilterableRunner(); } } private void warnAboutUnfilterableRunner() { logger.warn(() -> "Runner " + getRunnerToReport().getClass().getName() // + " (used on class " + getLegacyReportingName() + ") does not support filtering" // + " and will therefore be run completely."); } public Optional> getFilters() { return Optional.ofNullable(filters); } public void clearFilters() { this.filters = null; } public void applyFilters(Consumer childrenCreator) { if (filters != null && !filters.isEmpty()) { if (runner instanceof Filterable) { this.runner = toRequest().filterWith(new OrFilter(filters)).getRunner(); this.description = runner.getDescription(); this.children.clear(); childrenCreator.accept(this); } else { warnAboutUnfilterableRunner(); } } clearFilters(); } private Runner getRunnerToReport() { return (runner instanceof RunnerDecorator) ? ((RunnerDecorator) runner).getDecoratedRunner() : runner; } public boolean isIgnored() { return ignored; } private static class ExcludeDescriptionFilter extends Filter { private final Description description; private boolean successful; ExcludeDescriptionFilter(Description description) { this.description = description; } @Override public boolean shouldRun(Description description) { if (this.description.equals(description)) { successful = true; return false; } return true; } @Override public String describe() { return "exclude " + description; } boolean wasSuccessful() { return successful; } } } TestSourceProvider.java000066400000000000000000000057531455764576500353230ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static java.util.Collections.synchronizedMap; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apiguardian.api.API; import org.junit.platform.commons.support.ModifierSupport; import org.junit.platform.commons.util.LruCache; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.runner.Description; /** * @since 5.6 */ @API(status = INTERNAL, since = "5.6") public class TestSourceProvider { @SuppressWarnings("serial") private static final TestSource NULL_SOURCE = new TestSource() { }; private final Map testSourceCache = new ConcurrentHashMap<>(); private final Map, List> methodsCache = synchronizedMap(new LruCache<>(31)); public TestSource findTestSource(Description description) { TestSource testSource = testSourceCache.computeIfAbsent(description, this::computeTestSource); return testSource == NULL_SOURCE ? null : testSource; } private TestSource computeTestSource(Description description) { Class testClass = description.getTestClass(); if (testClass != null) { String methodName = DescriptionUtils.getMethodName(description); if (methodName != null) { Method method = findMethod(testClass, sanitizeMethodName(methodName)); if (method != null) { return MethodSource.from(testClass, method); } } return ClassSource.from(testClass); } return NULL_SOURCE; } private String sanitizeMethodName(String methodName) { if (methodName.contains("[") && methodName.endsWith("]")) { // special case for parameterized tests return methodName.substring(0, methodName.indexOf("[")); } return methodName; } private Method findMethod(Class testClass, String methodName) { List methods = methodsCache.computeIfAbsent(testClass, clazz -> findMethods(clazz, m -> true)).stream() // .filter(where(Method::getName, isEqual(methodName))) // .collect(toList()); if (methods.isEmpty()) { return null; } if (methods.size() == 1) { return methods.get(0); } methods = methods.stream().filter(ModifierSupport::isPublic).collect(toList()); if (methods.size() == 1) { return methods.get(0); } return null; } } VintageEngineDescriptor.java000066400000000000000000000016451455764576500362660ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Set; import org.apiguardian.api.API; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; /** * @since 5.6 */ @API(status = INTERNAL, since = "5.6") public class VintageEngineDescriptor extends EngineDescriptor { public VintageEngineDescriptor(UniqueId uniqueId) { super(uniqueId, "JUnit Vintage"); } public Set getModifiableChildren() { return children; } } VintageTestDescriptor.java000066400000000000000000000104221455764576500357710ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static java.util.Arrays.stream; import static java.util.function.Predicate.isEqual; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import org.apiguardian.api.API; import org.junit.experimental.categories.Category; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.runner.Description; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class VintageTestDescriptor extends AbstractTestDescriptor { public static final String ENGINE_ID = "junit-vintage"; public static final String SEGMENT_TYPE_RUNNER = "runner"; public static final String SEGMENT_TYPE_TEST = "test"; public static final String SEGMENT_TYPE_DYNAMIC = "dynamic"; protected Description description; public VintageTestDescriptor(UniqueId uniqueId, Description description, TestSource source) { this(uniqueId, description, generateDisplayName(description), source); } VintageTestDescriptor(UniqueId uniqueId, Description description, String displayName, TestSource source) { super(uniqueId, displayName, source); this.description = description; } private static String generateDisplayName(Description description) { String methodName = DescriptionUtils.getMethodName(description); return isNotBlank(methodName) ? methodName : description.getDisplayName(); } public Description getDescription() { return description; } @Override public String getLegacyReportingName() { String methodName = DescriptionUtils.getMethodName(description); if (methodName == null) { String className = description.getClassName(); if (isNotBlank(className)) { return className; } } return super.getLegacyReportingName(); } @Override public Type getType() { return description.isTest() ? Type.TEST : Type.CONTAINER; } @Override public Set getTags() { Set tags = new LinkedHashSet<>(); addTagsFromParent(tags); addCategoriesAsTags(tags); return tags; } @Override public void removeFromHierarchy() { if (canBeRemovedFromHierarchy()) { super.removeFromHierarchy(); } } protected boolean canBeRemovedFromHierarchy() { return tryToExcludeFromRunner(this.description); } protected boolean tryToExcludeFromRunner(Description description) { // @formatter:off return getParent().map(VintageTestDescriptor.class::cast) .map(parent -> parent.tryToExcludeFromRunner(description)) .orElse(false); // @formatter:on } void pruneDescriptorsForObsoleteDescriptions(List newSiblingDescriptions) { Optional newDescription = newSiblingDescriptions.stream().filter(isEqual(description)).findAny(); if (newDescription.isPresent()) { List newChildren = newDescription.get().getChildren(); new ArrayList<>(children).stream().map(VintageTestDescriptor.class::cast).forEach( childDescriptor -> childDescriptor.pruneDescriptorsForObsoleteDescriptions(newChildren)); } else { super.removeFromHierarchy(); } } private void addTagsFromParent(Set tags) { getParent().map(TestDescriptor::getTags).ifPresent(tags::addAll); } private void addCategoriesAsTags(Set tags) { Category annotation = description.getAnnotation(Category.class); if (annotation != null) { // @formatter:off stream(annotation.value()) .map(ReflectionUtils::getAllAssignmentCompatibleClasses) .flatMap(Collection::stream) .distinct() .map(Class::getName) .map(TestTag::create) .forEachOrdered(tags::add); // @formatter:on } } } package-info.java000066400000000000000000000001651455764576500340240ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/** * Test descriptors used within the JUnit Vintage test engine. */ package org.junit.vintage.engine.descriptor; junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/000077500000000000000000000000001455764576500305435ustar00rootroot00000000000000ClassSelectorResolver.java000066400000000000000000000057741455764576500356340ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static java.util.Collections.emptySet; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER; import java.util.Optional; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ClassFilter; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.UniqueId.Segment; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.discovery.SelectorResolver; import org.junit.runner.Runner; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; /** * @since 4.12 */ class ClassSelectorResolver implements SelectorResolver { private static final DefensiveAllDefaultPossibilitiesBuilder RUNNER_BUILDER = new DefensiveAllDefaultPossibilitiesBuilder(); private final ClassFilter classFilter; ClassSelectorResolver(ClassFilter classFilter) { this.classFilter = classFilter; } @Override public Resolution resolve(ClassSelector selector, Context context) { return resolveTestClass(selector.getJavaClass(), context); } @Override public Resolution resolve(UniqueIdSelector selector, Context context) { Segment lastSegment = selector.getUniqueId().getLastSegment(); if (SEGMENT_TYPE_RUNNER.equals(lastSegment.getType())) { String testClassName = lastSegment.getValue(); Class testClass = ReflectionUtils.tryToLoadClass(testClassName)// .getOrThrow(cause -> new JUnitException("Unknown class: " + testClassName, cause)); return resolveTestClass(testClass, context); } return unresolved(); } private Resolution resolveTestClass(Class testClass, Context context) { if (!classFilter.test(testClass)) { return unresolved(); } Runner runner = RUNNER_BUILDER.safeRunnerForClass(testClass); if (runner == null) { return unresolved(); } return context.addToParent(parent -> Optional.of(createRunnerTestDescriptor(parent, testClass, runner))).map( runnerTestDescriptor -> Match.exact(runnerTestDescriptor, () -> { runnerTestDescriptor.clearFilters(); return emptySet(); })).map(Resolution::match).orElse(unresolved()); } private RunnerTestDescriptor createRunnerTestDescriptor(TestDescriptor parent, Class testClass, Runner runner) { UniqueId uniqueId = parent.getUniqueId().append(SEGMENT_TYPE_RUNNER, testClass.getName()); return new RunnerTestDescriptor(uniqueId, testClass, runner, RUNNER_BUILDER.isIgnored(runner)); } } DefensiveAllDefaultPossibilitiesBuilder.java000066400000000000000000000116561455764576500412600ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import java.lang.reflect.Method; import java.util.function.Predicate; import org.junit.Ignore; import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; import org.junit.internal.builders.AnnotatedBuilder; import org.junit.internal.builders.IgnoredBuilder; import org.junit.internal.builders.IgnoredClassRunner; import org.junit.internal.builders.JUnit4Builder; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.runner.Runner; import org.junit.runner.manipulation.Filterable; import org.junit.runners.model.RunnerBuilder; /** * Customization of {@link AllDefaultPossibilitiesBuilder} from JUnit 4 to * ignore certain classes that would otherwise be reported as errors or cause * infinite recursion. * * @since 4.12 * @see DefensiveAnnotatedBuilder * @see DefensiveJUnit4Builder * @see IgnoredClassRunner */ class DefensiveAllDefaultPossibilitiesBuilder extends AllDefaultPossibilitiesBuilder { private static final Logger logger = LoggerFactory.getLogger(DefensiveAllDefaultPossibilitiesBuilder.class); private final AnnotatedBuilder annotatedBuilder; private final JUnit4Builder junit4Builder; private final IgnoredBuilder ignoredBuilder; @SuppressWarnings("deprecation") DefensiveAllDefaultPossibilitiesBuilder() { super(true); annotatedBuilder = new DefensiveAnnotatedBuilder(this); junit4Builder = new DefensiveJUnit4Builder(); ignoredBuilder = new NullIgnoredBuilder(); } @Override public Runner runnerForClass(Class testClass) throws Throwable { Runner runner = super.runnerForClass(testClass); if (testClass.getAnnotation(Ignore.class) != null) { if (runner == null) { return new IgnoredClassRunner(testClass); } return decorateIgnoredTestClass(runner); } return runner; } boolean isIgnored(Runner runner) { return runner instanceof IgnoredClassRunner || runner instanceof IgnoringRunnerDecorator; } /** * Instead of checking for the {@link Ignore} annotation and returning an * {@link IgnoredClassRunner} from {@link IgnoredBuilder}, we've let the * super class determine the regular runner that would have been used if * {@link Ignore} hadn't been present. Now, we decorate the runner to * override its runtime behavior (i.e. skip execution) but return its * regular {@link org.junit.runner.Description}. */ private IgnoringRunnerDecorator decorateIgnoredTestClass(Runner runner) { if (runner instanceof Filterable) { return new FilterableIgnoringRunnerDecorator(runner); } return new IgnoringRunnerDecorator(runner); } @Override protected AnnotatedBuilder annotatedBuilder() { return annotatedBuilder; } @Override protected JUnit4Builder junit4Builder() { return junit4Builder; } @Override protected IgnoredBuilder ignoredBuilder() { return ignoredBuilder; } /** * Customization of {@link AnnotatedBuilder} that ignores classes annotated * with {@code @RunWith(JUnitPlatform.class)} to avoid infinite recursion. */ private static class DefensiveAnnotatedBuilder extends AnnotatedBuilder { DefensiveAnnotatedBuilder(RunnerBuilder suiteBuilder) { super(suiteBuilder); } @Override public Runner buildRunner(Class runnerClass, Class testClass) throws Exception { // Referenced by name because it might not be available at runtime. if ("org.junit.platform.runner.JUnitPlatform".equals(runnerClass.getName())) { logger.warn(() -> "Ignoring test class using JUnitPlatform runner: " + testClass.getName()); return null; } return super.buildRunner(runnerClass, testClass); } } /** * Customization of {@link JUnit4Builder} that ignores classes that do not * contain any test methods in order not to report errors for them. */ private static class DefensiveJUnit4Builder extends JUnit4Builder { private static final Predicate isPotentialJUnit4TestMethod = new IsPotentialJUnit4TestMethod(); @Override public Runner runnerForClass(Class testClass) throws Throwable { if (containsTestMethods(testClass)) { return super.runnerForClass(testClass); } return null; } private boolean containsTestMethods(Class testClass) { return ReflectionUtils.isMethodPresent(testClass, isPotentialJUnit4TestMethod); } } /** * Customization of {@link IgnoredBuilder} that always returns {@code null}. * * @since 5.1 */ private static class NullIgnoredBuilder extends IgnoredBuilder { @Override public Runner runnerForClass(Class testClass) { // don't ignore entire test classes just yet return null; } } } FilterableIgnoringRunnerDecorator.java000066400000000000000000000021351455764576500401330ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import org.junit.platform.commons.util.Preconditions; import org.junit.runner.Runner; import org.junit.runner.manipulation.Filter; import org.junit.runner.manipulation.Filterable; import org.junit.runner.manipulation.NoTestsRemainException; /** * {@link Filterable} {@link IgnoringRunnerDecorator}. * * @since 5.1 */ class FilterableIgnoringRunnerDecorator extends IgnoringRunnerDecorator implements Filterable { FilterableIgnoringRunnerDecorator(Runner runner) { super(runner); Preconditions.condition(runner instanceof Filterable, () -> "Runner must be an instance of Filterable: " + runner.getClass().getName()); } @Override public void filter(Filter filter) throws NoTestsRemainException { ((Filterable) runner).filter(filter); } } IgnoringRunnerDecorator.java000066400000000000000000000024411455764576500361410ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import org.junit.platform.commons.util.Preconditions; import org.junit.runner.Description; import org.junit.runner.Runner; import org.junit.runner.notification.RunNotifier; import org.junit.vintage.engine.descriptor.RunnerDecorator; /** * Decorator for Runners that will be ignored completely. * *

Contrary to {@link org.junit.internal.builders.IgnoredClassRunner}, this * runner returns a complete description including all children. * * @since 5.1 */ class IgnoringRunnerDecorator extends Runner implements RunnerDecorator { protected final Runner runner; IgnoringRunnerDecorator(Runner runner) { this.runner = Preconditions.notNull(runner, "Runner must not be null"); } @Override public Description getDescription() { return runner.getDescription(); } @Override public void run(RunNotifier notifier) { notifier.fireTestIgnored(getDescription()); } @Override public Runner getDecoratedRunner() { return runner; } } IsPotentialJUnit4TestClass.java000066400000000000000000000022171455764576500364500ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.isAbstract; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import static org.junit.platform.commons.util.ReflectionUtils.isPublic; import java.util.function.Predicate; import org.apiguardian.api.API; /** * @since 4.12 */ @API(status = INTERNAL, since = "5.8", consumers = "org.junit.vintage.**") public class IsPotentialJUnit4TestClass implements Predicate> { @Override public boolean test(Class candidate) { // Do not collapse into a single return statement. if (!isPublic(candidate)) { return false; } if (isAbstract(candidate)) { return false; } if (isInnerClass(candidate)) { return false; } return true; } } IsPotentialJUnit4TestMethod.java000066400000000000000000000013501455764576500366200ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import java.lang.reflect.Method; import java.util.function.Predicate; import org.junit.Test; /** * @since 4.12 */ class IsPotentialJUnit4TestMethod implements Predicate { @Override public boolean test(Method method) { // Don't use AnnotationUtils.isAnnotated since JUnit 4 does not support // meta-annotations return method.isAnnotationPresent(Test.class); } } MethodSelectorResolver.java000066400000000000000000000106631455764576500360000ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.support.discovery.SelectorResolver.Resolution.unresolved; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER; import java.util.Optional; import java.util.function.Function; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.discovery.SelectorResolver; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import org.junit.vintage.engine.descriptor.DescriptionUtils; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; /** * @since 4.12 */ class MethodSelectorResolver implements SelectorResolver { @Override public Resolution resolve(MethodSelector selector, Context context) { Class testClass = selector.getJavaClass(); return resolveParentAndAddFilter(context, selectClass(testClass), parent -> toMethodFilter(selector)); } @Override public Resolution resolve(UniqueIdSelector selector, Context context) { for (UniqueId current = selector.getUniqueId(); !current.getSegments().isEmpty(); current = current.removeLastSegment()) { if (SEGMENT_TYPE_RUNNER.equals(current.getLastSegment().getType())) { return resolveParentAndAddFilter(context, selectUniqueId(current), parent -> toUniqueIdFilter(parent, selector.getUniqueId())); } } return unresolved(); } private Resolution resolveParentAndAddFilter(Context context, DiscoverySelector selector, Function filterCreator) { return context.resolve(selector).flatMap(parent -> addFilter(parent, filterCreator)).map( this::toResolution).orElse(unresolved()); } private Optional addFilter(TestDescriptor parent, Function filterCreator) { if (parent instanceof RunnerTestDescriptor) { RunnerTestDescriptor runnerTestDescriptor = (RunnerTestDescriptor) parent; runnerTestDescriptor.getFilters().ifPresent( filters -> filters.add(filterCreator.apply(runnerTestDescriptor))); return Optional.of(runnerTestDescriptor); } return Optional.empty(); } private Resolution toResolution(RunnerTestDescriptor parent) { return Resolution.match(Match.partial(parent)); } private Filter toMethodFilter(MethodSelector methodSelector) { Class testClass = methodSelector.getJavaClass(); String methodName = methodSelector.getMethodName(); return matchMethodDescription(Description.createTestDescription(testClass, methodName)); } private Filter toUniqueIdFilter(RunnerTestDescriptor runnerTestDescriptor, UniqueId uniqueId) { return new UniqueIdFilter(runnerTestDescriptor, uniqueId); } /** * The method {@link Filter#matchMethodDescription(Description)} returns a * filter that does not account for the case when the description is for a * {@link org.junit.runners.Parameterized} runner. */ private static Filter matchMethodDescription(final Description desiredDescription) { String desiredMethodName = DescriptionUtils.getMethodName(desiredDescription); return new Filter() { @Override public boolean shouldRun(Description description) { if (description.isTest()) { return desiredDescription.equals(description) || isParameterizedMethod(description); } // explicitly check if any children want to run for (Description each : description.getChildren()) { if (shouldRun(each)) { return true; } } return false; } private boolean isParameterizedMethod(Description description) { String methodName = DescriptionUtils.getMethodName(description); return methodName.startsWith(desiredMethodName + "["); } @Override public String describe() { return String.format("Method %s", desiredDescription.getDisplayName()); } }; } } RunnerTestDescriptorPostProcessor.java000066400000000000000000000057661455764576500402630ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toCollection; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.function.IntFunction; import org.junit.platform.engine.UniqueId; import org.junit.runner.Description; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.TestSourceProvider; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; import org.junit.vintage.engine.support.UniqueIdReader; import org.junit.vintage.engine.support.UniqueIdStringifier; /** * @since 5.5 */ class RunnerTestDescriptorPostProcessor { private final UniqueIdReader uniqueIdReader = new UniqueIdReader(); private final UniqueIdStringifier uniqueIdStringifier = new UniqueIdStringifier(); private final TestSourceProvider testSourceProvider = new TestSourceProvider(); void applyFiltersAndCreateDescendants(RunnerTestDescriptor runnerTestDescriptor) { addChildrenRecursively(runnerTestDescriptor); runnerTestDescriptor.applyFilters(this::addChildrenRecursively); } private void addChildrenRecursively(VintageTestDescriptor parent) { if (parent.getDescription().isTest()) { return; } List children = parent.getDescription().getChildren(); // Use LinkedHashMap to preserve order, ArrayList for fast access by index Map> childrenByUniqueId = children.stream().collect( groupingBy(uniqueIdReader.andThen(uniqueIdStringifier), LinkedHashMap::new, toCollection(ArrayList::new))); for (Entry> entry : childrenByUniqueId.entrySet()) { String uniqueId = entry.getKey(); List childrenWithSameUniqueId = entry.getValue(); IntFunction uniqueIdGenerator = determineUniqueIdGenerator(uniqueId, childrenWithSameUniqueId); for (int index = 0; index < childrenWithSameUniqueId.size(); index++) { String reallyUniqueId = uniqueIdGenerator.apply(index); Description description = childrenWithSameUniqueId.get(index); UniqueId id = parent.getUniqueId().append(VintageTestDescriptor.SEGMENT_TYPE_TEST, reallyUniqueId); VintageTestDescriptor child = new VintageTestDescriptor(id, description, testSourceProvider.findTestSource(description)); parent.addChild(child); addChildrenRecursively(child); } } } private IntFunction determineUniqueIdGenerator(String uniqueId, List childrenWithSameUniqueId) { if (childrenWithSameUniqueId.size() == 1) { return index -> uniqueId; } return index -> uniqueId + "[" + index + "]"; } } UniqueIdFilter.java000066400000000000000000000052501455764576500342220ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static java.util.stream.Collectors.toSet; import java.util.ArrayDeque; import java.util.Collections; import java.util.Deque; import java.util.Optional; import java.util.Set; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; /** * @since 4.12 */ class UniqueIdFilter extends Filter { private final RunnerTestDescriptor runnerTestDescriptor; private final UniqueId uniqueId; private Deque path; private Set descendants; UniqueIdFilter(RunnerTestDescriptor runnerTestDescriptor, UniqueId uniqueId) { this.runnerTestDescriptor = runnerTestDescriptor; this.uniqueId = uniqueId; } private void ensureInitialized() { if (descendants == null) { Optional identifiedTestDescriptor = runnerTestDescriptor.findByUniqueId(uniqueId); descendants = determineDescendants(identifiedTestDescriptor); path = determinePath(runnerTestDescriptor, identifiedTestDescriptor); } } private Deque determinePath(RunnerTestDescriptor runnerTestDescriptor, Optional identifiedTestDescriptor) { Deque path = new ArrayDeque<>(); Optional current = identifiedTestDescriptor; while (current.isPresent() && !current.get().equals(runnerTestDescriptor)) { path.addFirst(((VintageTestDescriptor) current.get()).getDescription()); current = current.get().getParent(); } return path; } private Set determineDescendants(Optional identifiedTestDescriptor) { // @formatter:off return identifiedTestDescriptor.map( testDescriptor -> testDescriptor .getDescendants() .stream() .map(VintageTestDescriptor.class::cast) .map(VintageTestDescriptor::getDescription) .collect(toSet())) .orElseGet(Collections::emptySet); // @formatter:on } @Override public boolean shouldRun(Description description) { ensureInitialized(); return path.contains(description) || descendants.contains(description); } @Override public String describe() { return "Unique ID " + uniqueId; } } VintageDiscoverer.java000066400000000000000000000040751455764576500347600ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; import org.junit.platform.commons.util.ClassFilter; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageEngineDescriptor; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class VintageDiscoverer { private static final IsPotentialJUnit4TestClass isPotentialJUnit4TestClass = new IsPotentialJUnit4TestClass(); // @formatter:off private static final EngineDiscoveryRequestResolver resolver = EngineDiscoveryRequestResolver.builder() .addClassContainerSelectorResolver(isPotentialJUnit4TestClass) .addSelectorResolver(context -> new ClassSelectorResolver(ClassFilter.of(context.getClassNameFilter(), isPotentialJUnit4TestClass))) .addSelectorResolver(new MethodSelectorResolver()) .build(); // @formatter:on public VintageEngineDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { VintageEngineDescriptor engineDescriptor = new VintageEngineDescriptor(uniqueId); resolver.resolve(discoveryRequest, engineDescriptor); RunnerTestDescriptorPostProcessor postProcessor = new RunnerTestDescriptorPostProcessor(); for (TestDescriptor testDescriptor : engineDescriptor.getChildren()) { RunnerTestDescriptor runnerTestDescriptor = (RunnerTestDescriptor) testDescriptor; postProcessor.applyFiltersAndCreateDescendants(runnerTestDescriptor); } return engineDescriptor; } } package-info.java000066400000000000000000000002021455764576500336450ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/** * Internal classes for test discovery within the JUnit Vintage test engine. */ package org.junit.vintage.engine.discovery; junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/000077500000000000000000000000001455764576500305375ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/EventType.java000066400000000000000000000006501455764576500333260ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.execution; /** * @since 5.4.1 */ enum EventType { REPORTED, SYNTHETIC } RunListenerAdapter.java000066400000000000000000000243741455764576500351100ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.execution; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_DYNAMIC; import java.util.Optional; import java.util.function.Function; import org.junit.Ignore; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.runner.Description; import org.junit.runner.Result; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.TestSourceProvider; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; import org.junit.vintage.engine.support.UniqueIdReader; import org.junit.vintage.engine.support.UniqueIdStringifier; /** * @since 4.12 */ class RunListenerAdapter extends RunListener { private final TestRun testRun; private final EngineExecutionListener listener; private final TestSourceProvider testSourceProvider; private final Function uniqueIdExtractor; RunListenerAdapter(TestRun testRun, EngineExecutionListener listener, TestSourceProvider testSourceProvider) { this.testRun = testRun; this.listener = listener; this.testSourceProvider = testSourceProvider; this.uniqueIdExtractor = new UniqueIdReader().andThen(new UniqueIdStringifier()); } @Override public void testRunStarted(Description description) { if (description.isSuite() && !testRun.getRunnerTestDescriptor().isIgnored()) { fireExecutionStarted(testRun.getRunnerTestDescriptor(), EventType.REPORTED); } } @Override public void testSuiteStarted(Description description) { RunnerTestDescriptor runnerTestDescriptor = testRun.getRunnerTestDescriptor(); // runnerTestDescriptor is reported in testRunStarted if (!runnerTestDescriptor.getDescription().equals(description)) { testStarted(lookupOrRegisterNextTestDescriptor(description), EventType.REPORTED); } } @Override public void testIgnored(Description description) { TestDescriptor testDescriptor = lookupOrRegisterNextTestDescriptor(description); String reason = determineReasonForIgnoredTest(testDescriptor, description).orElse(""); testIgnored(testDescriptor, reason); } @Override public void testStarted(Description description) { testStarted(lookupOrRegisterNextTestDescriptor(description), EventType.REPORTED); } @Override public void testAssumptionFailure(Failure failure) { handleFailure(failure, TestExecutionResult::aborted); } @Override public void testFailure(Failure failure) { handleFailure(failure, TestExecutionResult::failed); } @Override public void testFinished(Description description) { testFinished(lookupOrRegisterCurrentTestDescriptor(description)); } @Override public void testSuiteFinished(Description description) { RunnerTestDescriptor runnerTestDescriptor = testRun.getRunnerTestDescriptor(); // runnerTestDescriptor is reported in testRunFinished if (!runnerTestDescriptor.getDescription().equals(description)) { reportContainerFinished(lookupOrRegisterCurrentTestDescriptor(description)); } } @Override public void testRunFinished(Result result) { reportContainerFinished(testRun.getRunnerTestDescriptor()); } private void reportContainerFinished(TestDescriptor containerTestDescriptor) { if (testRun.isNotSkipped(containerTestDescriptor)) { if (testRun.isNotStarted(containerTestDescriptor)) { fireExecutionStarted(containerTestDescriptor, EventType.SYNTHETIC); } testRun.getInProgressTestDescriptorsWithSyntheticStartEvents().stream() // .filter(this::canFinish) // .forEach(this::fireExecutionFinished); if (testRun.isNotFinished(containerTestDescriptor)) { fireExecutionFinished(containerTestDescriptor); } } } private TestDescriptor lookupOrRegisterNextTestDescriptor(Description description) { return lookupOrRegisterTestDescriptor(description, testRun::lookupNextTestDescriptor); } private TestDescriptor lookupOrRegisterCurrentTestDescriptor(Description description) { return lookupOrRegisterTestDescriptor(description, testRun::lookupCurrentTestDescriptor); } private TestDescriptor lookupOrRegisterTestDescriptor(Description description, Function> lookup) { return lookup.apply(description).orElseGet(() -> registerDynamicTestDescriptor(description, lookup)); } private VintageTestDescriptor registerDynamicTestDescriptor(Description description, Function> lookup) { // workaround for dynamic children as used by Spock's Runner TestDescriptor parent = findParent(description, lookup); UniqueId uniqueId = parent.getUniqueId().append(SEGMENT_TYPE_DYNAMIC, uniqueIdExtractor.apply(description)); VintageTestDescriptor dynamicDescriptor = new VintageTestDescriptor(uniqueId, description, testSourceProvider.findTestSource(description)); parent.addChild(dynamicDescriptor); testRun.registerDynamicTest(dynamicDescriptor); dynamicTestRegistered(dynamicDescriptor); return dynamicDescriptor; } private TestDescriptor findParent(Description description, Function> lookup) { // @formatter:off return Optional.ofNullable(description.getTestClass()) .map(Description::createSuiteDescription) .flatMap(lookup) .orElseGet(testRun::getRunnerTestDescriptor); // @formatter:on } private void handleFailure(Failure failure, Function resultCreator) { handleFailure(failure, resultCreator, lookupOrRegisterCurrentTestDescriptor(failure.getDescription())); } private void handleFailure(Failure failure, Function resultCreator, TestDescriptor testDescriptor) { TestExecutionResult result = resultCreator.apply(failure.getException()); testRun.storeResult(testDescriptor, result); if (testRun.isNotStarted(testDescriptor)) { testStarted(testDescriptor, EventType.SYNTHETIC); } if (testRun.isNotFinished(testDescriptor) && testDescriptor.isContainer() && testRun.hasSyntheticStartEvent(testDescriptor) && testRun.isDescendantOfRunnerTestDescriptor(testDescriptor)) { testFinished(testDescriptor); } } private void testIgnored(TestDescriptor testDescriptor, String reason) { fireExecutionFinishedForInProgressNonAncestorTestDescriptorsWithSyntheticStartEvents(testDescriptor); fireExecutionStartedIncludingUnstartedAncestors(testDescriptor.getParent()); fireExecutionSkipped(testDescriptor, reason); } private Optional determineReasonForIgnoredTest(TestDescriptor testDescriptor, Description description) { Optional reason = getReason(description.getAnnotation(Ignore.class)); if (reason.isPresent()) { return reason; } // Workaround for some runners (e.g. JUnit38ClassRunner) don't include the @Ignore annotation // in the description, so we read it from the test class directly return testDescriptor.getSource() // .filter(ClassSource.class::isInstance) // .map(source -> ((ClassSource) source).getJavaClass()) // .flatMap(testClass -> getReason(testClass.getAnnotation(Ignore.class))); } private static Optional getReason(Ignore annotation) { return Optional.ofNullable(annotation).map(Ignore::value); } private void dynamicTestRegistered(TestDescriptor testDescriptor) { fireExecutionStartedIncludingUnstartedAncestors(testDescriptor.getParent()); listener.dynamicTestRegistered(testDescriptor); } private void testStarted(TestDescriptor testDescriptor, EventType eventType) { fireExecutionFinishedForInProgressNonAncestorTestDescriptorsWithSyntheticStartEvents(testDescriptor); fireExecutionStartedIncludingUnstartedAncestors(testDescriptor.getParent()); fireExecutionStarted(testDescriptor, eventType); } private void fireExecutionFinishedForInProgressNonAncestorTestDescriptorsWithSyntheticStartEvents( TestDescriptor testDescriptor) { testRun.getInProgressTestDescriptorsWithSyntheticStartEvents().stream() // .filter(it -> !isAncestor(it, testDescriptor) && canFinish(it)) // .forEach(this::fireExecutionFinished); } private boolean isAncestor(TestDescriptor candidate, TestDescriptor testDescriptor) { Optional parent = testDescriptor.getParent(); if (!parent.isPresent()) { return false; } if (parent.get().equals(candidate)) { return true; } return isAncestor(candidate, parent.get()); } private void testFinished(TestDescriptor descriptor) { fireExecutionFinished(descriptor); } private void fireExecutionStartedIncludingUnstartedAncestors(Optional parent) { if (parent.isPresent() && canStart(parent.get())) { fireExecutionStartedIncludingUnstartedAncestors(parent.get().getParent()); fireExecutionStarted(parent.get(), EventType.SYNTHETIC); } } private boolean canStart(TestDescriptor testDescriptor) { return testRun.isNotStarted(testDescriptor) // && (testDescriptor.equals(testRun.getRunnerTestDescriptor()) || testRun.isDescendantOfRunnerTestDescriptor(testDescriptor)); } private boolean canFinish(TestDescriptor testDescriptor) { return testRun.isNotFinished(testDescriptor) // && testRun.isDescendantOfRunnerTestDescriptor(testDescriptor) && testRun.areAllFinishedOrSkipped(testDescriptor.getChildren()); } private void fireExecutionSkipped(TestDescriptor testDescriptor, String reason) { testRun.markSkipped(testDescriptor); listener.executionSkipped(testDescriptor, reason); } private void fireExecutionStarted(TestDescriptor testDescriptor, EventType eventType) { testRun.markStarted(testDescriptor, eventType); listener.executionStarted(testDescriptor); } private void fireExecutionFinished(TestDescriptor testDescriptor) { testRun.markFinished(testDescriptor); listener.executionFinished(testDescriptor, testRun.getStoredResultOrSuccessful(testDescriptor)); } } RunnerExecutor.java000066400000000000000000000037651455764576500343260ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.execution; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.engine.TestExecutionResult.failed; import org.apiguardian.api.API; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestExecutionResult; import org.junit.runner.JUnitCore; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.TestSourceProvider; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class RunnerExecutor { private final EngineExecutionListener engineExecutionListener; private final TestSourceProvider testSourceProvider = new TestSourceProvider(); public RunnerExecutor(EngineExecutionListener engineExecutionListener) { this.engineExecutionListener = engineExecutionListener; } public void execute(RunnerTestDescriptor runnerTestDescriptor) { TestRun testRun = new TestRun(runnerTestDescriptor); JUnitCore core = new JUnitCore(); core.addListener(new RunListenerAdapter(testRun, engineExecutionListener, testSourceProvider)); try { core.run(runnerTestDescriptor.toRequest()); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); reportUnexpectedFailure(testRun, runnerTestDescriptor, failed(t)); } } private void reportUnexpectedFailure(TestRun testRun, RunnerTestDescriptor runnerTestDescriptor, TestExecutionResult result) { if (testRun.isNotStarted(runnerTestDescriptor)) { engineExecutionListener.executionStarted(runnerTestDescriptor); } engineExecutionListener.executionFinished(runnerTestDescriptor, result); } } junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java000066400000000000000000000234601455764576500330130ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.execution; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static java.util.stream.Stream.concat; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.runner.Description; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; import org.opentest4j.MultipleFailuresError; /** * @since 4.12 */ class TestRun { private final RunnerTestDescriptor runnerTestDescriptor; private final Set runnerDescendants; private final Map descriptionToDescriptors; private final Map> executionResults = new LinkedHashMap<>(); private final Set skippedDescriptors = new LinkedHashSet<>(); private final Set startedDescriptors = new HashSet<>(); private final Map inProgressDescriptors = new LinkedHashMap<>(); private final Set finishedDescriptors = new LinkedHashSet<>(); private final ThreadLocal> inProgressDescriptorsByStartingThread = ThreadLocal.withInitial( ArrayDeque::new); TestRun(RunnerTestDescriptor runnerTestDescriptor) { this.runnerTestDescriptor = runnerTestDescriptor; runnerDescendants = new LinkedHashSet<>(runnerTestDescriptor.getDescendants()); // @formatter:off descriptionToDescriptors = concat(Stream.of(runnerTestDescriptor), runnerDescendants.stream()) .map(VintageTestDescriptor.class::cast) .collect(toMap(VintageTestDescriptor::getDescription, VintageDescriptors::new, VintageDescriptors::merge, HashMap::new)); // @formatter:on } void registerDynamicTest(VintageTestDescriptor testDescriptor) { descriptionToDescriptors.computeIfAbsent(testDescriptor.getDescription(), __ -> new VintageDescriptors()).add( testDescriptor); runnerDescendants.add(testDescriptor); } RunnerTestDescriptor getRunnerTestDescriptor() { return runnerTestDescriptor; } Collection getInProgressTestDescriptorsWithSyntheticStartEvents() { List result = inProgressDescriptors.entrySet().stream() // .filter(entry -> entry.getValue().equals(EventType.SYNTHETIC)) // .map(Entry::getKey) // .collect(toCollection(ArrayList::new)); Collections.reverse(result); return result; } boolean isDescendantOfRunnerTestDescriptor(TestDescriptor testDescriptor) { return runnerDescendants.contains(testDescriptor); } boolean hasSyntheticStartEvent(TestDescriptor testDescriptor) { return inProgressDescriptors.get(testDescriptor) == EventType.SYNTHETIC; } Optional lookupNextTestDescriptor(Description description) { return lookupUnambiguouslyOrApplyFallback(description, VintageDescriptors::getNextUnstarted); } Optional lookupCurrentTestDescriptor(Description description) { return lookupUnambiguouslyOrApplyFallback(description, __ -> { VintageTestDescriptor lastStarted = inProgressDescriptorsByStartingThread.get().peekLast(); if (lastStarted != null && description.equals(lastStarted.getDescription())) { return Optional.of(lastStarted); } return Optional.empty(); }); } private Optional lookupUnambiguouslyOrApplyFallback(Description description, Function> fallback) { VintageDescriptors vintageDescriptors = descriptionToDescriptors.getOrDefault(description, VintageDescriptors.NONE); Optional result = vintageDescriptors.getUnambiguously(description); if (!result.isPresent()) { result = fallback.apply(vintageDescriptors); } return result; } void markSkipped(TestDescriptor testDescriptor) { skippedDescriptors.add(testDescriptor); if (testDescriptor instanceof VintageTestDescriptor) { VintageTestDescriptor vintageDescriptor = (VintageTestDescriptor) testDescriptor; descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); } } boolean isNotSkipped(TestDescriptor testDescriptor) { return !isSkipped(testDescriptor); } boolean isSkipped(TestDescriptor testDescriptor) { return skippedDescriptors.contains(testDescriptor); } void markStarted(TestDescriptor testDescriptor, EventType eventType) { inProgressDescriptors.put(testDescriptor, eventType); startedDescriptors.add(testDescriptor); if (testDescriptor instanceof VintageTestDescriptor) { VintageTestDescriptor vintageDescriptor = (VintageTestDescriptor) testDescriptor; inProgressDescriptorsByStartingThread.get().addLast(vintageDescriptor); descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); } } boolean isNotStarted(TestDescriptor testDescriptor) { return !startedDescriptors.contains(testDescriptor); } void markFinished(TestDescriptor testDescriptor) { inProgressDescriptors.remove(testDescriptor); finishedDescriptors.add(testDescriptor); if (testDescriptor instanceof VintageTestDescriptor) { VintageTestDescriptor descriptor = (VintageTestDescriptor) testDescriptor; inProgressDescriptorsByStartingThread.get().removeLastOccurrence(descriptor); } } boolean isNotFinished(TestDescriptor testDescriptor) { return !isFinished(testDescriptor); } boolean isFinished(TestDescriptor testDescriptor) { return finishedDescriptors.contains(testDescriptor); } boolean areAllFinishedOrSkipped(Set testDescriptors) { return testDescriptors.stream().allMatch(this::isFinishedOrSkipped); } boolean isFinishedOrSkipped(TestDescriptor testDescriptor) { return isFinished(testDescriptor) || isSkipped(testDescriptor); } void storeResult(TestDescriptor testDescriptor, TestExecutionResult result) { List testExecutionResults = executionResults.computeIfAbsent(testDescriptor, key -> new ArrayList<>()); testExecutionResults.add(result); } TestExecutionResult getStoredResultOrSuccessful(TestDescriptor testDescriptor) { List testExecutionResults = executionResults.get(testDescriptor); if (testExecutionResults == null) { return successful(); } if (testExecutionResults.size() == 1) { return testExecutionResults.get(0); } // @formatter:off List failures = testExecutionResults .stream() .map(TestExecutionResult::getThrowable) .map(Optional::get) .collect(toList()); // @formatter:on MultipleFailuresError multipleFailuresError = new MultipleFailuresError("", failures); failures.forEach(multipleFailuresError::addSuppressed); return failed(multipleFailuresError); } private static class VintageDescriptors { private static final VintageDescriptors NONE = new VintageDescriptors(emptyList()); private final List descriptors; private int skippedOrStartedCount; static VintageDescriptors merge(VintageDescriptors a, VintageDescriptors b) { List mergedDescriptors = new ArrayList<>( a.descriptors.size() + b.descriptors.size()); mergedDescriptors.addAll(a.descriptors); mergedDescriptors.addAll(b.descriptors); return new VintageDescriptors(mergedDescriptors); } VintageDescriptors(VintageTestDescriptor vintageTestDescriptor) { this(); add(vintageTestDescriptor); } VintageDescriptors() { this(new ArrayList<>(1)); } VintageDescriptors(List descriptors) { this.descriptors = descriptors; } void add(VintageTestDescriptor descriptor) { descriptors.add(descriptor); } /** * Returns the {@link TestDescriptor} that represents the specified * {@link Description}. * *

There are edge cases where multiple {@link Description Descriptions} * with the same {@code uniqueId} exist, e.g. when using overloaded methods * to define {@linkplain org.junit.experimental.theories.Theory theories}. * In this case, we try to find the correct {@link TestDescriptor} by * checking for object identity on the {@link Description} it represents. * * @param description the {@code Description} to look up */ Optional getUnambiguously(Description description) { if (descriptors.isEmpty()) { return Optional.empty(); } if (descriptors.size() == 1) { return Optional.of(descriptors.get(0)); } // @formatter:off return descriptors.stream() .filter(testDescriptor -> description == testDescriptor.getDescription()) .findFirst(); // @formatter:on } public void incrementSkippedOrStarted() { skippedOrStartedCount++; } public Optional getNextUnstarted() { if (skippedOrStartedCount < descriptors.size()) { return Optional.of(descriptors.get(skippedOrStartedCount)); } return Optional.empty(); } } } package-info.java000066400000000000000000000002021455764576500336410ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/** * Internal classes for test execution within the JUnit Vintage test engine. */ package org.junit.vintage.engine.execution; junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/package-info.java000066400000000000000000000001361455764576500317230ustar00rootroot00000000000000/** * Core package for the JUnit Vintage test engine. */ package org.junit.vintage.engine; junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/000077500000000000000000000000001455764576500302505ustar00rootroot00000000000000UniqueIdReader.java000066400000000000000000000031251455764576500337030ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.support; import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue; import java.io.Serializable; import java.util.function.Function; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.runner.Description; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class UniqueIdReader implements Function { private static final Logger logger = LoggerFactory.getLogger(UniqueIdReader.class); private final String fieldName; public UniqueIdReader() { this("fUniqueId"); } // For tests only UniqueIdReader(String fieldName) { this.fieldName = fieldName; } @Override public Serializable apply(Description description) { // @formatter:off return tryToReadFieldValue(Description.class, fieldName, description) .andThenTry(Serializable.class::cast) .ifFailure(cause -> logger.warn(cause, () -> format("Could not read unique ID for Description; using display name instead: %s", description))) .toOptional() .orElseGet(description::getDisplayName); // @formatter:on } } UniqueIdStringifier.java000066400000000000000000000032551455764576500347720ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.support; import static org.apiguardian.api.API.Status.INTERNAL; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.NumberFormat; import java.util.Base64; import java.util.Locale; import java.util.function.Function; import org.apiguardian.api.API; /** * @since 4.12 */ @API(status = INTERNAL, since = "4.12") public class UniqueIdStringifier implements Function { static final Charset CHARSET = StandardCharsets.UTF_8; @Override public String apply(Serializable uniqueId) { if (uniqueId instanceof CharSequence) { return uniqueId.toString(); } if (uniqueId instanceof Number) { return NumberFormat.getInstance(Locale.US).format(uniqueId); } return encodeBase64(serialize(uniqueId)); } private byte[] serialize(Serializable uniqueId) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); try (ObjectOutputStream out = new ObjectOutputStream(byteStream)) { out.writeObject(uniqueId); } catch (IOException e) { return uniqueId.toString().getBytes(CHARSET); } return byteStream.toByteArray(); } private String encodeBase64(byte[] bytes) { return new String(Base64.getEncoder().encode(bytes), CHARSET); } } junit5-r5.10.2/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/package-info.java000066400000000000000000000002311455764576500334330ustar00rootroot00000000000000/** * Internal support classes for test discovery and execution within the JUnit * Vintage test engine. */ package org.junit.vintage.engine.support; junit5-r5.10.2/junit-vintage-engine/src/main/resources/000077500000000000000000000000001455764576500230035ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/resources/META-INF/000077500000000000000000000000001455764576500241435ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/resources/META-INF/services/000077500000000000000000000000001455764576500257665ustar00rootroot00000000000000org.junit.platform.engine.TestEngine000066400000000000000000000000521455764576500347010ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/main/resources/META-INF/servicesorg.junit.vintage.engine.VintageTestEnginejunit5-r5.10.2/junit-vintage-engine/src/module/000077500000000000000000000000001455764576500213325ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/module/org.junit.vintage.engine/000077500000000000000000000000001455764576500261515ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/module/org.junit.vintage.engine/module-info.java000066400000000000000000000014751455764576500312410ustar00rootroot00000000000000/* * Copyright 2015-2021 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ /** * Provides a {@linkplain org.junit.platform.engine.TestEngine} for running * JUnit 3 and 4 based tests on the platform. * * @since 4.12 * @provides org.junit.platform.engine.TestEngine The {@code VintageTestEngine} * runs JUnit 3 and 4 based tests on the platform. */ module org.junit.vintage.engine { requires junit; // 4 requires static org.apiguardian.api; requires org.junit.platform.engine; provides org.junit.platform.engine.TestEngine with org.junit.vintage.engine.VintageTestEngine; } junit5-r5.10.2/junit-vintage-engine/src/test/000077500000000000000000000000001455764576500210245ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/000077500000000000000000000000001455764576500217455ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/000077500000000000000000000000001455764576500225345ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/000077500000000000000000000000001455764576500236655ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/000077500000000000000000000000001455764576500253225ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/000077500000000000000000000000001455764576500265675ustar00rootroot00000000000000JUnit4ParameterizedTests.java000066400000000000000000000051111455764576500342260ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.vintage.engine.samples.junit4.JUnit4ParameterizedTestCase; /** * @since 4.12 */ class JUnit4ParameterizedTests { private final Map callCounts = new HashMap<>(); @Test void selectingWholeParameterizedClassRunsTestsWithAllValues() { executeTests(selectClass(JUnit4ParameterizedTestCase.class)); Map expectedCallCounts = new HashMap<>(); expectedCallCounts.put(SUCCESSFUL, 3); expectedCallCounts.put(FAILED, 9); assertEquals(expectedCallCounts, callCounts); } @Test void selectingOneTestFromParameterizedClassRunsWithAllValues() { executeTests(selectMethod(JUnit4ParameterizedTestCase.class, "test1")); assertEquals(Map.of(FAILED, 3), callCounts); } private void executeTests(DiscoverySelector selector) { var launcher = LauncherFactory.create(); launcher.registerTestExecutionListeners(new StatusTrackingListener()); // @formatter:off launcher.execute( request() .selectors(selector) .filters(includeEngines("junit-vintage")) .build() ); // @formatter:on } private class StatusTrackingListener implements TestExecutionListener { @Override public void executionFinished(TestIdentifier identifier, TestExecutionResult result) { if (identifier.isTest()) { callCounts.merge(result.getStatus(), 1, Integer::sum); } } } } JUnit4VersionCheckTests.java000066400000000000000000000056321455764576500340250ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; /** * @since 5.4 */ class JUnit4VersionCheckTests { /** * @since 5.7 */ @Test void handlesParsingSupportedVersionIdWithStandardVersionFormat() { assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.12")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.13")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.13.1")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.13.2")); } /** * @since 5.7 */ @Test void handlesParsingSupportedVersionIdWithCustomizedVersionFormat() { assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.12-patch_1")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.12.0")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.12.0.1")); assertDoesNotThrow(() -> JUnit4VersionCheck.checkSupported(() -> "4.12.0.patch-042")); } @Test void throwsExceptionForUnsupportedVersion() { var exception = assertThrows(JUnitException.class, () -> JUnit4VersionCheck.checkSupported(() -> "4.11")); assertEquals("Unsupported version of junit:junit: 4.11. Please upgrade to version 4.12 or later.", exception.getMessage()); } @Test void handlesErrorsReadingVersion() { Error error = new NoClassDefFoundError(); var exception = assertThrows(JUnitException.class, () -> JUnit4VersionCheck.checkSupported(() -> { throw error; })); assertEquals("Failed to read version of junit:junit", exception.getMessage()); assertSame(error, exception.getCause()); } @Test void handlesErrorsParsingVersion() { var exception = assertThrows(JUnitException.class, () -> JUnit4VersionCheck.checkSupported(() -> "not a version")); assertEquals("Failed to parse version of junit:junit: not a version", exception.getMessage()); } @Test @Tag("missing-junit4") void handlesMissingJUnit() { var exception = assertThrows(JUnitException.class, JUnit4VersionCheck::checkSupported); assertEquals("Invalid class/module path: junit-vintage-engine is present but junit:junit is not. " + "Please either remove junit-vintage-engine or add junit:junit, or alternatively use " + "an excludeEngines(\"junit-vintage\") filter.", exception.getMessage()); } } VintageLauncherIntegrationTests.java000066400000000000000000000301171455764576500356630ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.includedIf; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.TagFilter.excludeTags; import static org.junit.platform.launcher.TagFilter.includeTags; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.internal.runners.SuiteMethod; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.runners.Suite; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit3.PlainJUnit3TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.Categories; import org.junit.vintage.engine.samples.junit4.EnclosedJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteOfSuiteWithFilterableChildRunner; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithTwoTestCases; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithNotFilterableRunner; import org.junit.vintage.engine.samples.junit4.NotFilterableRunner; import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithTwoTestMethods; /** * @since 5.1 */ class VintageLauncherIntegrationTests { @Test void executesOnlyTaggedMethodOfRegularTestClass() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var request = request() // .selectors(selectClass(testClass)) // .filters(includeTags(Categories.Failing.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(2); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), "failingTest"); } @Test void executesIncludedTaggedMethodOfNestedTestClass() { Class testClass = EnclosedJUnit4TestCase.class; Class nestedTestClass = EnclosedJUnit4TestCase.NestedClass.class; var request = request() // .selectors(selectClass(testClass)) // .filters(includeTags(Categories.Failing.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), nestedTestClass.getName(), "failingTest"); } @Test void executesOnlyNotExcludedTaggedMethodOfNestedTestClass() { Class testClass = EnclosedJUnit4TestCase.class; Class nestedTestClass = EnclosedJUnit4TestCase.NestedClass.class; var request = request() // .selectors(selectClass(testClass)) // .filters(excludeTags(Categories.Failing.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), nestedTestClass.getName(), "successfulTest"); } @Test void removesWholeSubtree() { Class testClass = EnclosedJUnit4TestCase.class; var request = request() // .selectors(selectClass(testClass)) // .filters(excludeTags(Categories.Plain.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty(); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage"); } @Test void removesCompleteClassIfNoMethodHasMatchingTags() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var request = request() // .selectors(selectClass(testClass)) // .filters(includeTags("wrong-tag")); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty(); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactly("JUnit Vintage"); } @Test void removesCompleteClassIfItHasExcludedTag() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var request = request() // .selectors(selectClass(testClass)) // .filters(excludeTags(Categories.Plain.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty(); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactly("JUnit Vintage"); } @TrackLogRecords @Test void executesAllTestsForNotFilterableRunner(LogRecordListener logRecordListener) { Class testClass = JUnit4TestCaseWithNotFilterableRunner.class; var request = request() // .selectors(selectClass(testClass)) // .filters((PostDiscoveryFilter) descriptor -> includedIf(descriptor.getDisplayName().contains("#1"))); var testPlan = discover(request); logRecordListener.clear(); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), "Test #0", "Test #1"); assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Runner " + NotFilterableRunner.class.getName() + " (used on class " + testClass.getName() + ")" // + " does not support filtering and will therefore be run completely."); } @TrackLogRecords @Test void executesAllTestsForNotFilterableChildRunnerOfSuite(LogRecordListener logRecordListener) { Class suiteClass = JUnit4SuiteOfSuiteWithFilterableChildRunner.class; Class testClass = JUnit4TestCaseWithNotFilterableRunner.class; var request = request() // .selectors(selectClass(suiteClass)) // .filters((PostDiscoveryFilter) descriptor -> includedIf(descriptor.getDisplayName().contains("#1"))); var testPlan = discover(request); logRecordListener.clear(); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(4); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(), "Test #0", "Test #1"); assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) // .containsExactly("Runner " + Suite.class.getName() + " (used on class " + suiteClass.getName() + ")" // + " was not able to satisfy all filter requests."); } @TrackLogRecords @Test void executesAllTestsWhenFilterDidNotExcludeTestForJUnit3Suite(LogRecordListener logRecordListener) { Class suiteClass = JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails.class; Class testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class; var request = request() // .selectors(selectClass(suiteClass)) // .filters((PostDiscoveryFilter) descriptor -> excluded("not today")); var testPlan = discover(request); logRecordListener.clear(); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(), "test"); assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Runner " + SuiteMethod.class.getName() + " (used on class " + suiteClass.getName() + ")" // + " was not able to satisfy all filter requests."); } @Test void executesOnlyTaggedMethodsForSuite() { Class suiteClass = JUnit4SuiteWithTwoTestCases.class; Class testClass = PlainJUnit4TestCaseWithTwoTestMethods.class; var request = request() // .selectors(selectClass(suiteClass)) // .filters(includeTags(Categories.Successful.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(), "successfulTest"); } @Test void removesCompleteClassWithNotFilterableRunnerIfItHasExcludedTag() { Class testClass = JUnit4TestCaseWithNotFilterableRunner.class; var request = request() // .selectors(selectClass(testClass)) // .filters(excludeTags(Categories.Successful.class.getName())); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty(); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactly("JUnit Vintage"); } @Test void filtersOutAllDescendantsOfParameterizedTestCase() { Class testClass = ParameterizedTestCase.class; var request = request() // .selectors(selectClass(testClass)) // .filters((PostDiscoveryFilter) descriptor -> excluded("excluded")); var testPlan = discover(request); assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty(); var results = execute(request); assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) // .containsExactly("JUnit Vintage"); } private TestPlan discover(LauncherDiscoveryRequestBuilder requestBuilder) { var launcher = LauncherFactory.create(); return launcher.discover(toRequest(requestBuilder)); } private Map execute(LauncherDiscoveryRequestBuilder requestBuilder) { Map results = new LinkedHashMap<>(); var request = toRequest(requestBuilder); var launcher = LauncherFactory.create(); launcher.execute(request, new TestExecutionListener() { @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { results.put(testIdentifier, testExecutionResult); } }); return results; } private LauncherDiscoveryRequest toRequest(LauncherDiscoveryRequestBuilder requestBuilder) { return requestBuilder.filters(includeEngines(ENGINE_ID)).build(); } } VintageTestEngineBasicTests.java000066400000000000000000000017031455764576500347240ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * Basic assertions regarding {@link org.junit.platform.engine.TestEngine} * functionality in JUnit Vintage. * * @since 4.12 */ class VintageTestEngineBasicTests { private final VintageTestEngine vintage = new VintageTestEngine(); @Test void id() { assertEquals("junit-vintage", vintage.getId()); } @Test void groupId() { assertEquals("org.junit.vintage", vintage.getGroupId().get()); } @Test void artifactId() { assertEquals("junit-vintage-engine", vintage.getArtifactId().get()); } } VintageTestEngineDiscoveryTests.java000066400000000000000000001047331455764576500356610ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static java.text.MessageFormat.format; import static java.util.function.Predicate.isEqual; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.discovery.PackageNameFilter.includePackageNames; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.runner.manipulation.Filter; import org.junit.vintage.engine.samples.PlainOldJavaClassWithoutAnyTestsTestCase; import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit3.PlainJUnit3TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.Categories.Failing; import org.junit.vintage.engine.samples.junit4.Categories.Plain; import org.junit.vintage.engine.samples.junit4.Categories.Skipped; import org.junit.vintage.engine.samples.junit4.Categories.SkippedWithReason; import org.junit.vintage.engine.samples.junit4.EmptyIgnoredTestCase; import org.junit.vintage.engine.samples.junit4.IgnoredJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithJUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithTwoTestCases; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithDistinguishableOverloadedMethod; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithIndistinguishableOverloadedMethod; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithNotFilterableRunner; import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleInheritedTestWhichFails; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichIsIgnored; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithTwoTestMethods; import org.junit.vintage.engine.samples.junit4.SingleFailingTheoryTestCase; import org.junit.vintage.engine.samples.junit4.TestCaseRunWithJUnitPlatformRunner; /** * @since 4.12 */ class VintageTestEngineDiscoveryTests { VintageTestEngine engine = new VintageTestEngine(); @Test void resolvesSimpleJUnit4TestClass() throws Exception { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesIgnoredJUnit4TestClass() throws Exception { Class testClass = IgnoredJUnit4TestCase.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); assertThat(runnerDescriptor.getChildren()).hasSize(2); List children = new ArrayList<>(runnerDescriptor.getChildren()); assertTestMethodDescriptor(children.get(0), testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); assertTestMethodDescriptor(children.get(1), testClass, "succeedingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesEmptyIgnoredTestClass() { Class testClass = EmptyIgnoredTestCase.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertFalse(runnerDescriptor.isContainer()); assertTrue(runnerDescriptor.isTest()); assertEquals(testClass.getSimpleName(), runnerDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForClass(testClass), runnerDescriptor.getUniqueId()); assertThat(runnerDescriptor.getChildren()).isEmpty(); } @Test void resolvesJUnit4TestClassWithCustomRunner() throws Exception { Class testClass = SingleFailingTheoryTestCase.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "theory", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesJUnit3TestCase() throws Exception { Class testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "test", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesJUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails() throws Exception { Class suiteClass = JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails.class; Class testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class; var discoveryRequest = discoveryRequestForClass(suiteClass); var engineDescriptor = discoverTests(discoveryRequest); var suiteDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(suiteDescriptor, suiteClass); assertThat(suiteDescriptor.getDisplayName()).describedAs("display name") // .startsWith(suiteClass.getSimpleName()); assertThat(suiteDescriptor.getLegacyReportingName()).describedAs("legacy reporting name") // .isEqualTo(suiteClass.getName()); var testClassDescriptor = getOnlyElement(suiteDescriptor.getChildren()); assertContainerTestDescriptor(testClassDescriptor, suiteClass, testClass); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertTestMethodDescriptor(testMethodDescriptor, testClass, "test", VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass)); } @Test void resolvesJUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored() throws Exception { Class suiteClass = JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored.class; Class testClass = PlainJUnit4TestCaseWithSingleTestWhichIsIgnored.class; var discoveryRequest = discoveryRequestForClass(suiteClass); var engineDescriptor = discoverTests(discoveryRequest); var suiteDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(suiteDescriptor, suiteClass); var testClassDescriptor = getOnlyElement(suiteDescriptor.getChildren()); assertContainerTestDescriptor(testClassDescriptor, suiteClass, testClass); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertTestMethodDescriptor(testMethodDescriptor, testClass, "ignoredTest", VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass)); } @Test void resolvesJUnit4TestCaseWithIndistinguishableOverloadedMethod() { Class testClass = JUnit4TestCaseWithIndistinguishableOverloadedMethod.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); List testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren()); assertThat(testMethodDescriptors).hasSize(2); var testMethodDescriptor = testMethodDescriptors.get(0); assertEquals("theory", testMethodDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "theory", "0"), testMethodDescriptor.getUniqueId()); assertClassSource(testClass, testMethodDescriptor); testMethodDescriptor = testMethodDescriptors.get(1); assertEquals("theory", testMethodDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "theory", "1"), testMethodDescriptor.getUniqueId()); assertClassSource(testClass, testMethodDescriptor); } @Test void resolvesJUnit4TestCaseWithDistinguishableOverloadedMethod() throws Exception { Class testClass = JUnit4TestCaseWithDistinguishableOverloadedMethod.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); List testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren()); var testMethodDescriptor = getOnlyElement(testMethodDescriptors); assertEquals("test", testMethodDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "test"), testMethodDescriptor.getUniqueId()); assertMethodSource(testClass.getMethod("test"), testMethodDescriptor); } @Test void doesNotResolvePlainOldJavaClassesWithoutAnyTest() { assertYieldsNoDescriptors(PlainOldJavaClassWithoutAnyTestsTestCase.class); } @Test void doesNotResolveClassRunWithJUnitPlatform() { assertYieldsNoDescriptors(TestCaseRunWithJUnitPlatformRunner.class); } @Test void resolvesClasspathSelector() throws Exception { var root = getClasspathRoot(PlainJUnit4TestCaseWithSingleTestWhichFails.class); var discoveryRequest = request().selectors(selectClasspathRoots(Set.of(root))).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .contains(PlainJUnit4TestCaseWithSingleTestWhichFails.class.getSimpleName()) .contains(PlainJUnit3TestCaseWithSingleTestWhichFails.class.getSimpleName()) .doesNotContain(PlainOldJavaClassWithoutAnyTestsTestCase.class.getSimpleName()); // @formatter:on } @Test void resolvesClasspathSelectorForJarFile() throws Exception { var jarUrl = getClass().getResource("/vintage-testjar.jar"); var jarFile = Paths.get(jarUrl.toURI()); var originalClassLoader = Thread.currentThread().getContextClassLoader(); try (var classLoader = new URLClassLoader(new URL[] { jarUrl })) { Thread.currentThread().setContextClassLoader(classLoader); var discoveryRequest = request().selectors(selectClasspathRoots(Set.of(jarFile))).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .containsExactly("JUnit4Test"); // @formatter:on } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } @Test void resolvesApplyingClassNameFilters() throws Exception { var root = getClasspathRoot(PlainJUnit4TestCaseWithSingleTestWhichFails.class); var discoveryRequest = request().selectors(selectClasspathRoots(Set.of(root))).filters( includeClassNamePatterns(".*JUnit4.*"), includeClassNamePatterns(".*Plain.*")).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .contains(PlainJUnit4TestCaseWithSingleTestWhichFails.class.getSimpleName()) .doesNotContain(JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getSimpleName()) .doesNotContain(PlainJUnit3TestCaseWithSingleTestWhichFails.class.getSimpleName()); // @formatter:on } @Test void resolvesApplyingPackageNameFilters() throws Exception { var root = getClasspathRoot(PlainJUnit4TestCaseWithSingleTestWhichFails.class); var discoveryRequest = request().selectors(selectClasspathRoots(Set.of(root))).filters( includePackageNames("org"), includePackageNames("org.junit")).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .contains(PlainJUnit4TestCaseWithSingleTestWhichFails.class.getSimpleName()); // @formatter:on } @Test void resolvesPackageSelectorForJUnit4SamplesPackage() { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; var discoveryRequest = request().selectors(selectPackage(testClass.getPackage().getName())).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .contains(testClass.getSimpleName()) .doesNotContain(PlainJUnit3TestCaseWithSingleTestWhichFails.class.getSimpleName()); // @formatter:on } @Test void resolvesPackageSelectorForJUnit3SamplesPackage() { Class testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class; var discoveryRequest = request().selectors(selectPackage(testClass.getPackage().getName())).build(); var engineDescriptor = discoverTests(discoveryRequest); // @formatter:off assertThat(engineDescriptor.getChildren()) .extracting(TestDescriptor::getDisplayName) .contains(testClass.getSimpleName()) .doesNotContain(PlainJUnit4TestCaseWithSingleTestWhichFails.class.getSimpleName()); // @formatter:on } @Test void resolvesClassesWithInheritedMethods() throws Exception { Class superclass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; Class testClass = PlainJUnit4TestCaseWithSingleInheritedTestWhichFails.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertEquals(testClass.getSimpleName(), runnerDescriptor.getDisplayName()); assertClassSource(testClass, runnerDescriptor); var testDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertEquals("failingTest", testDescriptor.getDisplayName()); assertMethodSource(testClass, superclass.getMethod("failingTest"), testDescriptor); } @Test void resolvesCategoriesIntoTags() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = discoveryRequestForClass(testClass); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(runnerDescriptor.getTags()).containsOnly(TestTag.create(Plain.class.getName())); var failingTest = findChildByDisplayName(runnerDescriptor, "failingTest"); assertThat(failingTest.getTags()).containsOnly(// TestTag.create(Plain.class.getName()), // TestTag.create(Failing.class.getName())); var ignoredWithoutReason = findChildByDisplayName(runnerDescriptor, "ignoredTest1_withoutReason"); assertThat(ignoredWithoutReason.getTags()).containsOnly(// TestTag.create(Plain.class.getName()), // TestTag.create(Skipped.class.getName())); var ignoredWithReason = findChildByDisplayName(runnerDescriptor, "ignoredTest2_withReason"); assertThat(ignoredWithReason.getTags()).containsOnly(// TestTag.create(Plain.class.getName()), // TestTag.create(Skipped.class.getName()), // TestTag.create(SkippedWithReason.class.getName())); } @Test void resolvesMethodSelectorForSingleMethod() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors(selectMethod(testClass, testClass.getMethod("failingTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesMethodOfIgnoredJUnit4TestClass() throws Exception { Class testClass = IgnoredJUnit4TestCase.class; var discoveryRequest = request().selectors(selectMethod(testClass, testClass.getMethod("failingTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesMethodSelectorForTwoMethodsOfSameClass() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors(selectMethod(testClass, testClass.getMethod("failingTest")), selectMethod(testClass, testClass.getMethod("successfulTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); List testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren()); assertThat(testMethodDescriptors).hasSize(2); var failingTest = testMethodDescriptors.get(0); assertTestMethodDescriptor(failingTest, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); var successfulTest = testMethodDescriptors.get(1); assertTestMethodDescriptor(successfulTest, testClass, "successfulTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesUniqueIdSelectorForSingleMethod() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "failingTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var childDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(childDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void resolvesUniqueIdSelectorForSingleClass() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClass(testClass))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); assertThat(runnerDescriptor.getChildren()).hasSize(5); } @Test void resolvesUniqueIdSelectorOfSingleClassWithinSuite() throws Exception { Class suiteClass = JUnit4SuiteWithTwoTestCases.class; Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; var discoveryRequest = request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass))).build(); var engineDescriptor = discoverTests(discoveryRequest); var suiteDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(suiteDescriptor, suiteClass); var testClassDescriptor = getOnlyElement(suiteDescriptor.getChildren()); assertContainerTestDescriptor(testClassDescriptor, suiteClass, testClass); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertTestMethodDescriptor(testMethodDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass)); } @Test void resolvesUniqueIdSelectorOfSingleMethodWithinSuite() throws Exception { Class suiteClass = JUnit4SuiteWithTwoTestCases.class; Class testClass = PlainJUnit4TestCaseWithTwoTestMethods.class; var discoveryRequest = request().selectors(selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod( VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass), testClass, "successfulTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var suiteDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(suiteDescriptor, suiteClass); var testClassDescriptor = getOnlyElement(suiteDescriptor.getChildren()); assertContainerTestDescriptor(testClassDescriptor, suiteClass, testClass); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertTestMethodDescriptor(testMethodDescriptor, testClass, "successfulTest", VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass)); } @Test void resolvesMultipleUniqueIdSelectorsForMethodsOfSameClass() throws Exception { Class testClass = PlainJUnit4TestCaseWithTwoTestMethods.class; var discoveryRequest = request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "successfulTest")), selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "failingTest"))).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); List testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren()); assertThat(testMethodDescriptors).hasSize(2); assertTestMethodDescriptor(testMethodDescriptors.get(0), testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); assertTestMethodDescriptor(testMethodDescriptors.get(1), testClass, "successfulTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void doesNotResolveMissingUniqueIdSelectorForSingleClass() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClass(testClass) + "/[test:doesNotExist]")).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var testDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertInitializationError(testDescriptor, Filter.class, testClass); } @Test void ignoresMoreFineGrainedSelectorsWhenClassIsSelectedAsWell() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( // selectMethod(testClass, testClass.getMethod("failingTest")), // selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "abortedTest")), selectClass(testClass) // ).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); assertThat(runnerDescriptor.getChildren()).hasSize(5); } @Test void resolvesCombinationOfMethodAndUniqueIdSelector() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( // selectMethod(testClass, testClass.getMethod("failingTest")), // selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "abortedTest") // )).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); List testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren()); assertThat(testMethodDescriptors).hasSize(2); assertTestMethodDescriptor(testMethodDescriptors.get(0), testClass, "abortedTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); assertTestMethodDescriptor(testMethodDescriptors.get(1), testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void ignoresRedundantSelector() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; var discoveryRequest = request().selectors( // selectMethod(testClass, testClass.getMethod("failingTest")), // selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "failingTest") // )).build(); var engineDescriptor = discoverTests(discoveryRequest); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var testMethodDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertTestMethodDescriptor(testMethodDescriptor, testClass, "failingTest", VintageUniqueIdBuilder.uniqueIdForClass(testClass)); } @Test void doesNotResolveMethodOfClassNotAcceptedByClassNameFilter() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; // @formatter:off var request = request() .selectors(selectMethod(testClass, testClass.getMethod("failingTest"))) .filters(includeClassNamePatterns("Foo")) .build(); // @formatter:on assertYieldsNoDescriptors(request); } @Test void doesNotResolveMethodOfClassNotAcceptedByPackageNameFilter() throws Exception { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; // @formatter:off var request = request() .selectors(selectMethod(testClass, testClass.getMethod("failingTest"))) .filters(includePackageNames("com.acme")) .build(); // @formatter:on assertYieldsNoDescriptors(request); } @Test void resolvesClassForMethodSelectorForClassWithNonFilterableRunner() { Class testClass = JUnit4TestCaseWithNotFilterableRunner.class; // @formatter:off var request = request() .selectors(selectUniqueId(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "Test #0"))) .build(); // @formatter:on var engineDescriptor = discoverTests(request); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertEquals(testClass.getSimpleName(), runnerDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForClass(testClass), runnerDescriptor.getUniqueId()); assertThat(runnerDescriptor.getChildren()).isNotEmpty(); } @Test void usesCustomUniqueIdsAndDisplayNamesWhenPresent() { Class suiteClass = JUnit4SuiteWithJUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.class; var request = request().selectors(selectClass(suiteClass)).build(); var engineDescriptor = discoverTests(request); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, suiteClass); var testClassDescriptor = getOnlyElement(runnerDescriptor.getChildren()); assertEquals("(TestClass)", testClassDescriptor.getDisplayName()); var childDescriptor = getOnlyElement(testClassDescriptor.getChildren()); var prefix = VintageUniqueIdBuilder.uniqueIdForClass(suiteClass); assertThat(childDescriptor.getUniqueId().toString()).startsWith(prefix.toString()); assertEquals("(TestMethod)", childDescriptor.getDisplayName()); var customUniqueIdValue = childDescriptor.getUniqueId().getSegments().get(2).getType(); assertNotNull(Base64.getDecoder().decode(customUniqueIdValue.getBytes(StandardCharsets.UTF_8)), "is a valid Base64 encoding scheme"); } @Test void resolvesTestSourceForParameterizedTests() throws Exception { Class testClass = ParameterizedTestCase.class; var request = request().selectors(selectClass(testClass)).build(); var engineDescriptor = discoverTests(request); var runnerDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertRunnerTestDescriptor(runnerDescriptor, testClass); var fooParentDescriptor = findChildByDisplayName(runnerDescriptor, "[foo]"); assertTrue(fooParentDescriptor.isContainer()); assertFalse(fooParentDescriptor.isTest()); assertThat(fooParentDescriptor.getSource()).isEmpty(); var testMethodDescriptor = getOnlyElement(fooParentDescriptor.getChildren()); assertEquals("test[foo]", testMethodDescriptor.getDisplayName()); assertTrue(testMethodDescriptor.isTest()); assertFalse(testMethodDescriptor.isContainer()); assertMethodSource(testClass.getMethod("test"), testMethodDescriptor); } private TestDescriptor findChildByDisplayName(TestDescriptor runnerDescriptor, String displayName) { // @formatter:off var children = runnerDescriptor.getChildren(); return children .stream() .filter(where(TestDescriptor::getDisplayName, isEqual(displayName))) .findAny() .orElseThrow(() -> new AssertionError(format("No child with display name \"{0}\" in {1}", displayName, children))); // @formatter:on } private TestDescriptor discoverTests(LauncherDiscoveryRequest discoveryRequest) { return engine.discover(discoveryRequest, UniqueId.forEngine(engine.getId())); } private Path getClasspathRoot(Class testClass) throws Exception { var location = testClass.getProtectionDomain().getCodeSource().getLocation(); return Paths.get(location.toURI()); } private void assertYieldsNoDescriptors(Class testClass) { var request = discoveryRequestForClass(testClass); assertYieldsNoDescriptors(request); } private void assertYieldsNoDescriptors(LauncherDiscoveryRequest request) { var engineDescriptor = discoverTests(request); assertThat(engineDescriptor.getChildren()).isEmpty(); } private static void assertRunnerTestDescriptor(TestDescriptor runnerDescriptor, Class testClass) { assertTrue(runnerDescriptor.isContainer()); assertFalse(runnerDescriptor.isTest()); assertEquals(testClass.getSimpleName(), runnerDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForClass(testClass), runnerDescriptor.getUniqueId()); assertClassSource(testClass, runnerDescriptor); } private static void assertTestMethodDescriptor(TestDescriptor testMethodDescriptor, Class testClass, String methodName, UniqueId uniqueContainerId) throws Exception { assertTrue(testMethodDescriptor.isTest()); assertFalse(testMethodDescriptor.isContainer()); assertEquals(methodName, testMethodDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForMethod(uniqueContainerId, testClass, methodName), testMethodDescriptor.getUniqueId()); assertThat(testMethodDescriptor.getChildren()).isEmpty(); assertMethodSource(testClass.getMethod(methodName), testMethodDescriptor); } private static void assertContainerTestDescriptor(TestDescriptor containerDescriptor, Class suiteClass, Class testClass) { assertTrue(containerDescriptor.isContainer()); assertFalse(containerDescriptor.isTest()); assertEquals(testClass.getName(), containerDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForClasses(suiteClass, testClass), containerDescriptor.getUniqueId()); assertClassSource(testClass, containerDescriptor); } private static void assertInitializationError(TestDescriptor testDescriptor, Class failingClass, Class testClass) { assertTrue(testDescriptor.isTest()); assertFalse(testDescriptor.isContainer()); assertEquals("initializationError", testDescriptor.getDisplayName()); assertEquals(VintageUniqueIdBuilder.uniqueIdForErrorInClass(testClass, failingClass), testDescriptor.getUniqueId()); assertThat(testDescriptor.getChildren()).isEmpty(); assertClassSource(failingClass, testDescriptor); } private static void assertClassSource(Class expectedClass, TestDescriptor testDescriptor) { assertThat(testDescriptor.getSource()).containsInstanceOf(ClassSource.class); var classSource = (ClassSource) testDescriptor.getSource().get(); assertThat(classSource.getJavaClass()).isEqualTo(expectedClass); } private static void assertMethodSource(Method expectedMethod, TestDescriptor testDescriptor) { assertMethodSource(expectedMethod.getDeclaringClass(), expectedMethod, testDescriptor); } private static void assertMethodSource(Class expectedClass, Method expectedMethod, TestDescriptor testDescriptor) { assertThat(testDescriptor.getSource()).containsInstanceOf(MethodSource.class); var methodSource = (MethodSource) testDescriptor.getSource().get(); assertThat(methodSource.getClassName()).isEqualTo(expectedClass.getName()); assertThat(methodSource.getMethodName()).isEqualTo(expectedMethod.getName()); assertThat(methodSource.getMethodParameterTypes()).isEqualTo( ClassUtils.nullSafeToString(expectedMethod.getParameterTypes())); } private static LauncherDiscoveryRequest discoveryRequestForClass(Class testClass) { return request().selectors(selectClass(testClass)).build(); } } VintageTestEngineExecutionTests.java000066400000000000000000001205441455764576500356530ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import static java.util.function.Predicate.isEqual; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.testkit.engine.EventConditions.abortedWithReason; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.dynamicTestRegistered; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.EventConditions.uniqueIdSubstring; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import static org.junit.runner.Description.createSuiteDescription; import static org.junit.runner.Description.createTestDescription; import java.math.BigDecimal; import junit.runner.Version; import org.assertj.core.api.Condition; import org.junit.AssumptionViolatedException; import org.junit.jupiter.api.Test; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.runner.Description; import org.junit.runner.RunWith; import org.junit.runner.Runner; import org.junit.runner.notification.RunNotifier; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import org.junit.vintage.engine.samples.junit3.IgnoredJUnit3TestCase; import org.junit.vintage.engine.samples.junit3.JUnit3ParallelSuiteWithSubsuites; import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSubsuites; import org.junit.vintage.engine.samples.junit3.JUnit4SuiteWithIgnoredJUnit3TestCase; import org.junit.vintage.engine.samples.junit3.PlainJUnit3TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.CompletelyDynamicTestCase; import org.junit.vintage.engine.samples.junit4.EmptyIgnoredTestCase; import org.junit.vintage.engine.samples.junit4.EnclosedJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.EnclosedWithParameterizedChildrenJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.IgnoredJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.IgnoredParameterizedTestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteOfSuiteWithIgnoredJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteOfSuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteOfSuiteWithJUnit4TestCaseWithErrorInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithExceptionThrowingRunner; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithIgnoredJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithJUnit3SuiteWithSingleTestCase; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished; import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithAssumptionFailureInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithErrorCollectorStoringMultipleFailures; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithErrorInAfterClass; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithErrorInBeforeClass; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithExceptionThrowingRunner; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithIndistinguishableOverloadedMethod; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames; import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions; import org.junit.vintage.engine.samples.junit4.MalformedJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase; import org.junit.vintage.engine.samples.junit4.ParameterizedTimingTestCase; import org.junit.vintage.engine.samples.junit4.ParameterizedWithAfterParamFailureTestCase; import org.junit.vintage.engine.samples.junit4.ParameterizedWithBeforeParamFailureTestCase; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithLifecycleMethods; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichIsIgnored; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithTwoTestMethods; import org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods; import org.opentest4j.MultipleFailuresError; /** * @since 4.12 */ class VintageTestEngineExecutionTests { @Test void executesPlainJUnit4TestCaseWithSingleTestWhichFails() { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionError.class), message("this test should fail"))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesPlainJUnit4TestCaseWithTwoTests() { Class testClass = PlainJUnit4TestCaseWithTwoTestMethods.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionError.class), message("this test should fail"))), // event(test("successfulTest"), started()), // event(test("successfulTest"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesPlainJUnit4TestCaseWithFiveTests() { Class testClass = PlainJUnit4TestCaseWithFiveTestMethods.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("abortedTest"), started()), // event(test("abortedTest"), abortedWithReason(instanceOf(AssumptionViolatedException.class), message("this test should be aborted"))), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionError.class), message("this test should fail"))), // event(test("ignoredTest1_withoutReason"), skippedWithReason("")), // event(test("ignoredTest2_withReason"), skippedWithReason("a custom reason")), // event(test("successfulTest"), started()), // event(test("successfulTest"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesEnclosedJUnit4TestCase() { Class testClass = EnclosedJUnit4TestCase.class; Class nestedClass = EnclosedJUnit4TestCase.NestedClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(nestedClass), started()), // event(test("successfulTest"), started()), // event(test("successfulTest"), finishedSuccessfully()), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionError.class), message("this test should fail"))), // event(container(nestedClass), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesEnclosedWithParameterizedChildrenJUnit4TestCase() { Class testClass = EnclosedWithParameterizedChildrenJUnit4TestCase.class; String commonNestedClassPrefix = EnclosedWithParameterizedChildrenJUnit4TestCase.class.getName() + "$NestedTestCase"; execute(testClass).allEvents().debug().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(commonNestedClassPrefix), started()), // event(container("[0]"), started()), // event(test("test[0]"), started()), // event(test("test[0]"), finishedSuccessfully()), // event(container("[0]"), finishedSuccessfully()), // event(container("[1]"), started()), // event(test("test[1]"), started()), // event(test("test[1]"), finishedSuccessfully()), // event(container("[1]"), finishedSuccessfully()), // event(container(commonNestedClassPrefix), finishedSuccessfully()), // event(container(commonNestedClassPrefix), started()), // event(container("[0]"), started()), // event(test("test[0]"), started()), // event(test("test[0]"), finishedSuccessfully()), // event(container("[0]"), finishedSuccessfully()), // event(container("[1]"), started()), // event(test("test[1]"), started()), // event(test("test[1]"), finishedSuccessfully()), // event(container("[1]"), finishedSuccessfully()), // event(container(commonNestedClassPrefix), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteWithJUnit3SuiteWithSingleTestCase() { Class junit4SuiteClass = JUnit4SuiteWithJUnit3SuiteWithSingleTestCase.class; Class testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class; execute(junit4SuiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(junit4SuiteClass), started()), // event(container("TestSuite with 1 tests"), started()), // event(container(testClass), started()), // event(test("test"), started()), // event(test("test"), finishedWithFailure(instanceOf(AssertionError.class), message("this test should fail"))), // event(container(testClass), finishedSuccessfully()), // event(container("TestSuite with 1 tests"), finishedSuccessfully()), // event(container(junit4SuiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesMalformedJUnit4TestCase() { Class testClass = MalformedJUnit4TestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("initializationError"), started()), // event(test("initializationError"), finishedWithFailure(message(it -> it.contains("Method nonPublicTest() should be public")))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithErrorInBeforeClass() { Class testClass = JUnit4TestCaseWithErrorInBeforeClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(AssertionError.class), message("something went wrong"))), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass() { Class suiteClass = JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass.class; Class testClass = JUnit4TestCaseWithErrorInBeforeClass.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(AssertionError.class), message("something went wrong"))), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteOfSuiteWithJUnit4TestCaseWithErrorInBeforeClass() { Class suiteOfSuiteClass = JUnit4SuiteOfSuiteWithJUnit4TestCaseWithErrorInBeforeClass.class; Class suiteClass = JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass.class; Class testClass = JUnit4TestCaseWithErrorInBeforeClass.class; execute(suiteOfSuiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteOfSuiteClass), started()), // event(container(suiteClass), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure(instanceOf(AssertionError.class), message("something went wrong"))), // event(container(suiteClass), finishedSuccessfully()), // event(container(suiteOfSuiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithAssumptionFailureInBeforeClass() { Class testClass = JUnit4TestCaseWithAssumptionFailureInBeforeClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), abortedWithReason(instanceOf(AssumptionViolatedException.class), message("assumption violated"))), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteOfSuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass() { Class suiteOfSuiteClass = JUnit4SuiteOfSuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass.class; Class suiteClass = JUnit4SuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass.class; Class testClass = JUnit4TestCaseWithAssumptionFailureInBeforeClass.class; execute(suiteOfSuiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteOfSuiteClass), started()), // event(container(suiteClass), started()), // event(container(testClass), started()), // event(container(testClass), abortedWithReason(instanceOf(AssumptionViolatedException.class), message("assumption violated"))), // event(container(suiteClass), finishedSuccessfully()), // event(container(suiteOfSuiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithErrorInAfterClass() { Class testClass = JUnit4TestCaseWithErrorInAfterClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure(instanceOf(AssertionError.class), message("expected to fail"))), // event(test("succeedingTest"), started()), // event(test("succeedingTest"), finishedSuccessfully()), // event(container(testClass), finishedWithFailure(instanceOf(AssertionError.class), message("error in @AfterClass"))), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithOverloadedMethod() { Class testClass = JUnit4TestCaseWithIndistinguishableOverloadedMethod.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[0]"), started()), // event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[0]"), finishedWithFailure()), // event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[1]"), started()), // event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[1]"), finishedWithFailure()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesIgnoredJUnit4TestCase() { Class testClass = IgnoredJUnit4TestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), skippedWithReason("complete class is ignored")), // event(engine(), finishedSuccessfully())); } @Test void executesEmptyIgnoredTestClass() { Class testClass = EmptyIgnoredTestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(test(testClass.getName()), skippedWithReason("empty")), // event(engine(), finishedSuccessfully())); } @Test void reportsExecutionEventsAroundLifecycleMethods() { Class testClass = PlainJUnit4TestCaseWithLifecycleMethods.class; PlainJUnit4TestCaseWithLifecycleMethods.EVENTS.clear(); var listener = new EngineExecutionListener() { @Override public void executionStarted(TestDescriptor testDescriptor) { PlainJUnit4TestCaseWithLifecycleMethods.EVENTS.add( "executionStarted:" + testDescriptor.getDisplayName()); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { PlainJUnit4TestCaseWithLifecycleMethods.EVENTS.add( "executionFinished:" + testDescriptor.getDisplayName()); } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { PlainJUnit4TestCaseWithLifecycleMethods.EVENTS.add( "executionSkipped:" + testDescriptor.getDisplayName()); } @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { } @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { } }; execute(testClass, listener); // @formatter:off assertThat(PlainJUnit4TestCaseWithLifecycleMethods.EVENTS).containsExactly( "executionStarted:JUnit Vintage", "executionStarted:" + testClass.getSimpleName(), "beforeClass", "executionStarted:failingTest", "before", "failingTest", "after", "executionFinished:failingTest", "executionSkipped:skippedTest", "executionStarted:succeedingTest", "before", "succeedingTest", "after", "executionFinished:succeedingTest", "afterClass", "executionFinished:" + testClass.getSimpleName(), "executionFinished:JUnit Vintage" ); // @formatter:on } @Test void executesJUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored() { Class suiteClass = JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored.class; Class testClass = PlainJUnit4TestCaseWithSingleTestWhichIsIgnored.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container(testClass), started()), // event(test("ignoredTest"), skippedWithReason("ignored test")), // event(container(testClass), finishedSuccessfully()), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteOfSuiteWithIgnoredJUnit4TestCase() { Class suiteOfSuiteClass = JUnit4SuiteOfSuiteWithIgnoredJUnit4TestCase.class; Class suiteClass = JUnit4SuiteWithIgnoredJUnit4TestCase.class; Class testClass = IgnoredJUnit4TestCase.class; execute(suiteOfSuiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteOfSuiteClass), started()), // event(container(suiteClass), started()), // event(container(testClass), skippedWithReason("complete class is ignored")), // event(container(suiteClass), finishedSuccessfully()), // event(container(suiteOfSuiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesParameterizedTestCase() { Class testClass = ParameterizedTestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container("[foo]"), started()), // event(test("test[foo]"), started()), // event(test("test[foo]"), finishedSuccessfully()), // event(container("[foo]"), finishedSuccessfully()), // event(container("[bar]"), started()), // event(test("test[bar]"), started()), // event(test("test[bar]"), finishedWithFailure(instanceOf(AssertionError.class), message("expected:<[foo]> but was:<[bar]>"))), // event(container("[bar]"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesIgnoredParameterizedTestCase() { Class testClass = IgnoredParameterizedTestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container("[foo]"), started()), // event(test("test[foo]"), skippedWithReason("")), // event(container("[foo]"), finishedSuccessfully()), // event(container("[bar]"), started()), // event(test("test[bar]"), skippedWithReason("")), // event(container("[bar]"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesParameterizedTimingTestCase() { assumeTrue(atLeastJUnit4_13(), "@BeforeParam and @AfterParam were introduced in JUnit 4.13"); Class testClass = ParameterizedTimingTestCase.class; var events = execute(testClass).allEvents().debug(); var firstParamStartedEvent = events.filter(event(container("[foo]"), started())::matches).findFirst() // .orElseThrow(() -> new AssertionError("No start event for [foo]")); var firstParamFinishedEvent = events.filter( event(container("[foo]"), finishedSuccessfully())::matches).findFirst() // .orElseThrow(() -> new AssertionError("No finish event for [foo]")); var secondParamStartedEvent = events.filter(event(container("[bar]"), started())::matches).findFirst() // .orElseThrow(() -> new AssertionError("No start event for [bar]")); var secondParamFinishedEvent = events.filter( event(container("[bar]"), finishedSuccessfully())::matches).findFirst() // .orElseThrow(() -> new AssertionError("No finish event for [bar]")); assertThat(ParameterizedTimingTestCase.EVENTS.get("beforeParam(foo)")).isAfterOrEqualTo( firstParamStartedEvent.getTimestamp()); assertThat(ParameterizedTimingTestCase.EVENTS.get("afterParam(foo)")).isBeforeOrEqualTo( firstParamFinishedEvent.getTimestamp()); assertThat(ParameterizedTimingTestCase.EVENTS.get("beforeParam(bar)")).isAfterOrEqualTo( secondParamStartedEvent.getTimestamp()); assertThat(ParameterizedTimingTestCase.EVENTS.get("afterParam(bar)")).isBeforeOrEqualTo( secondParamFinishedEvent.getTimestamp()); } @Test void executesParameterizedWithAfterParamFailureTestCase() { assumeTrue(atLeastJUnit4_13(), "@AfterParam was introduced in JUnit 4.13"); Class testClass = ParameterizedWithAfterParamFailureTestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container("[foo]"), started()), // event(test("test[foo]"), started()), // event(test("test[foo]"), finishedSuccessfully()), // event(container("[foo]"), finishedWithFailure(instanceOf(AssertionError.class))), // event(container("[bar]"), started()), // event(test("test[bar]"), started()), // event(test("test[bar]"), finishedWithFailure(instanceOf(AssertionError.class), message("expected:<[foo]> but was:<[bar]>"))), // event(container("[bar]"), finishedWithFailure(instanceOf(AssertionError.class))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesParameterizedWithBeforeParamFailureTestCase() { assumeTrue(atLeastJUnit4_13(), "@BeforeParam was introduced in JUnit 4.13"); Class testClass = ParameterizedWithBeforeParamFailureTestCase.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container("[foo]"), started()), // event(container("[foo]"), finishedWithFailure(instanceOf(AssertionError.class))), // event(container("[bar]"), started()), // event(container("[bar]"), finishedWithFailure(instanceOf(AssertionError.class))), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithExceptionThrowingRunner() { Class testClass = JUnit4TestCaseWithExceptionThrowingRunner.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(test(testClass.getName()), started()), // event(test(testClass.getName()), finishedWithFailure()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteWithExceptionThrowingRunner() { Class testClass = JUnit4SuiteWithExceptionThrowingRunner.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container(testClass), finishedWithFailure()), // event(engine(), finishedSuccessfully())); } public static class DynamicSuiteRunner extends Runner { private final Class testClass; public DynamicSuiteRunner(Class testClass) { this.testClass = testClass; } @Override public Description getDescription() { return createSuiteDescription(testClass); } @Override public void run(RunNotifier notifier) { var dynamicDescription = createTestDescription(testClass, "dynamicTest"); notifier.fireTestStarted(dynamicDescription); notifier.fireTestFinished(dynamicDescription); } } @RunWith(DynamicSuiteRunner.class) public static class DynamicTestClass { } @Test void reportsDynamicTestsForUnknownDescriptions() { Class testClass = DynamicTestClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(test(testClass.getName()), started()), // event(dynamicTestRegistered("dynamicTest")), // event(test("dynamicTest"), started()), // event(test("dynamicTest"), finishedSuccessfully()), // event(test(testClass.getName()), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } public static class DynamicAndStaticChildrenRunner extends Runner { private final Class testClass; public DynamicAndStaticChildrenRunner(Class testClass) { this.testClass = testClass; } @Override public Description getDescription() { var suiteDescription = createSuiteDescription(testClass); suiteDescription.addChild(createTestDescription(testClass, "staticTest")); return suiteDescription; } @Override public void run(RunNotifier notifier) { var staticDescription = getDescription().getChildren().get(0); notifier.fireTestStarted(staticDescription); notifier.fireTestFinished(staticDescription); var dynamicDescription = createTestDescription(testClass, "dynamicTest"); notifier.fireTestStarted(dynamicDescription); notifier.fireTestFinished(dynamicDescription); } } @RunWith(DynamicAndStaticChildrenRunner.class) public static class DynamicAndStaticTestClass { } @RunWith(Suite.class) @SuiteClasses(DynamicAndStaticTestClass.class) public static class SuiteWithDynamicAndStaticTestClass { } @Test void reportsIntermediateContainersFinishedAfterTheirDynamicChildren() { Class suiteClass = SuiteWithDynamicAndStaticTestClass.class; Class testClass = DynamicAndStaticTestClass.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass.getName()), started()), // event(container(testClass.getName()), started()), // event(test("staticTest"), started()), // event(test("staticTest"), finishedSuccessfully()), // event(dynamicTestRegistered("dynamicTest")), // event(test("dynamicTest"), started()), // event(test("dynamicTest"), finishedSuccessfully()), // event(container(testClass.getName()), finishedSuccessfully()), // event(container(suiteClass.getName()), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } public static class MisbehavingChildlessRunner extends Runner { private final Class testClass; public MisbehavingChildlessRunner(Class testClass) { this.testClass = testClass; } @Override public Description getDescription() { return createSuiteDescription(testClass); } @Override public void run(RunNotifier notifier) { notifier.fireTestStarted(createTestDescription(testClass, "doesNotExist")); } } @RunWith(MisbehavingChildlessRunner.class) public static class MisbehavingChildTestClass { } @Test void ignoreEventsForUnknownDescriptionsByMisbehavingChildlessRunner() { Class testClass = MisbehavingChildTestClass.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(test(testClass.getName()), started()), // event(dynamicTestRegistered("doesNotExist")), // event(test("doesNotExist"), started()), // event(test(testClass.getName()), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithRunnerWithCustomUniqueIds() { Class testClass = JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(uniqueIdSubstring(testClass.getName()), started()), // event(uniqueIdSubstring(testClass.getName()), finishedWithFailure()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithErrorCollectorStoringMultipleFailures() { Class testClass = JUnit4TestCaseWithErrorCollectorStoringMultipleFailures.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("example"), started()), // event(test("example"), // finishedWithFailure(// instanceOf(MultipleFailuresError.class), // new Condition<>(throwable -> ((MultipleFailuresError) throwable).getFailures().size() == 3, "MultipleFailuresError must contain 3 failures"), // new Condition<>(throwable -> ((MultipleFailuresError) throwable).getSuppressed().length == 3, "MultipleFailuresError must contain 3 suppressed exceptions")// )), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished() { Class testClass = JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("testWithMissingEvents"), started()), // event(test("testWithMissingEvents"), finishedWithFailure()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished() { Class suiteClass = JUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.class; Class firstTestClass = JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.class; Class secondTestClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container(firstTestClass), started()), // event(test("testWithMissingEvents"), started()), // event(test("testWithMissingEvents"), finishedWithFailure()), // event(container(firstTestClass), finishedSuccessfully()), // event(container(secondTestClass), started()), // event(test("failingTest"), started()), // event(test("failingTest"), finishedWithFailure()), // event(container(secondTestClass), finishedSuccessfully()), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesCompletelyDynamicTestCaseDiscoveredByUniqueId() { Class testClass = CompletelyDynamicTestCase.class; var request = LauncherDiscoveryRequestBuilder.request().selectors( selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClass(testClass))).build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(displayName(testClass.getSimpleName()), started()), // event(dynamicTestRegistered("Test #0")), // event(test("Test #0"), started()), // event(test("Test #0"), finishedSuccessfully()), // event(displayName(testClass.getSimpleName()), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit3ParallelSuiteWithSubsuites() { var suiteClass = JUnit3ParallelSuiteWithSubsuites.class; var results = execute(suiteClass); results.containerEvents() // .assertStatistics(stats -> stats.started(4).dynamicallyRegistered(0).finished(4).succeeded(4)) // .assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container("Case"), started()), // event(container("Case")), // event(container("Case")), // event(container("Case"), finishedSuccessfully()), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); results.testEvents() // .assertStatistics(stats -> stats.started(2).dynamicallyRegistered(0).finished(2).succeeded(2)) // .assertEventsMatchExactly( // event(test("hello"), started()), // event(test("hello")), // event(test("hello")), // event(test("hello"), finishedSuccessfully())); } @Test void executesJUnit3SuiteWithSubsuites() { var suiteClass = JUnit3SuiteWithSubsuites.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container("Case1"), started()), // event(test("hello"), started()), // event(test("hello"), finishedSuccessfully()), // event(container("Case1"), finishedSuccessfully()), // event(container("Case2"), started()), // event(test("hello"), started()), // event(test("hello"), finishedSuccessfully()), // event(container("Case2"), finishedSuccessfully()), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions() { Class testClass = JUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions.class; execute(testClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(container("1st"), started()), // event(test("0"), skippedWithReason(__ -> true)), // event(test("1"), started()), // event(test("1"), finishedSuccessfully()), // event(container("1st"), finishedSuccessfully()), // event(container("2nd"), started()), // event(test("0"), skippedWithReason(__ -> true)), // event(test("1"), started()), // event(test("1"), finishedSuccessfully()), // event(container("2nd"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesUnrolledSpockFeatureMethod() { Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; var request = LauncherDiscoveryRequestBuilder.request().selectors( selectMethod(testClass, "unrolled feature for #input")).build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(uniqueIdSubstring(testClass.getName()), started()), // event(dynamicTestRegistered("unrolled feature for 23")), // event(test("unrolled feature for 23"), started()), // event(test("unrolled feature for 23"), finishedWithFailure()), // event(dynamicTestRegistered("unrolled feature for 42")), // event(test("unrolled feature for 42"), started()), // event(test("unrolled feature for 42"), finishedSuccessfully()), // event(uniqueIdSubstring(testClass.getName()), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesRegularSpockFeatureMethod() { Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; var request = LauncherDiscoveryRequestBuilder.request().selectors(selectMethod(testClass, "regular")).build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // event(test("regular"), started()), // event(test("regular"), finishedSuccessfully()), // event(container(testClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } @Test void executesIgnoredJUnit3TestCase() { var suiteClass = IgnoredJUnit3TestCase.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), skippedWithReason(isEqual("testing"))), // event(engine(), finishedSuccessfully())); } @Test void executesJUnit4SuiteWithIgnoredJUnit3TestCase() { var suiteClass = JUnit4SuiteWithIgnoredJUnit3TestCase.class; var testClass = IgnoredJUnit3TestCase.class; execute(suiteClass).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(suiteClass), started()), // event(container(testClass), skippedWithReason(isEqual("testing"))), // event(container(suiteClass), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); } private static EngineExecutionResults execute(Class testClass) { return execute(request(testClass)); } private static EngineExecutionResults execute(LauncherDiscoveryRequest request) { return EngineTestKit.execute(new VintageTestEngine(), request); } private static void execute(Class testClass, EngineExecutionListener listener) { TestEngine testEngine = new VintageTestEngine(); var discoveryRequest = request(testClass); var engineTestDescriptor = testEngine.discover(discoveryRequest, UniqueId.forEngine(testEngine.getId())); testEngine.execute( new ExecutionRequest(engineTestDescriptor, listener, discoveryRequest.getConfigurationParameters())); } private static LauncherDiscoveryRequest request(Class testClass) { return LauncherDiscoveryRequestBuilder.request().selectors(selectClass(testClass)).build(); } private static boolean atLeastJUnit4_13() { return JUnit4VersionCheck.parseVersion(Version.id()).compareTo(new BigDecimal("4.13")) >= 0; } } VintageTestEngineTestSuite.java000066400000000000000000000021701455764576500346100ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; /** * Test suite for the {@link VintageTestEngine}. * *

Logging Configuration

* *

In order for our log4j2 configuration to be used in an IDE, you must * set the following system property before running any tests — for * example, in Run Configurations in Eclipse. * *

 * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
 * 
* * @since 4.12 */ @Suite @SelectPackages("org.junit.vintage.engine") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") class VintageTestEngineTestSuite { } VintageUniqueIdBuilder.java000066400000000000000000000045401455764576500337260ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine; import org.junit.platform.engine.UniqueId; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; /** * Test data builder for building unique IDs for the {@link VintageTestEngine}. * * Used to decouple tests from concrete unique ID strings. * * @since 4.12 */ public class VintageUniqueIdBuilder { public static UniqueId uniqueIdForErrorInClass(Class clazz, Class failingClass) { return uniqueIdForClasses(clazz).append(VintageTestDescriptor.SEGMENT_TYPE_TEST, "initializationError(" + failingClass.getName() + ")"); } public static UniqueId uniqueIdForClass(Class clazz) { return uniqueIdForClasses(clazz); } public static UniqueId uniqueIdForClasses(Class clazz, Class... clazzes) { var uniqueId = uniqueIdForClass(clazz.getName()); for (var each : clazzes) { uniqueId = uniqueId.append(VintageTestDescriptor.SEGMENT_TYPE_TEST, each.getName()); } return uniqueId; } public static UniqueId uniqueIdForClass(String fullyQualifiedClassName) { var containerId = engineId(); return containerId.append(VintageTestDescriptor.SEGMENT_TYPE_RUNNER, fullyQualifiedClassName); } public static UniqueId uniqueIdForMethod(Class testClass, String methodName) { return uniqueIdForClass(testClass).append(VintageTestDescriptor.SEGMENT_TYPE_TEST, methodValue(testClass, methodName)); } private static String methodValue(Class testClass, String methodName) { return methodName + "(" + testClass.getName() + ")"; } public static UniqueId uniqueIdForMethod(Class testClass, String methodName, String index) { return uniqueIdForClass(testClass).append(VintageTestDescriptor.SEGMENT_TYPE_TEST, methodValue(testClass, methodName) + "[" + index + "]"); } public static UniqueId uniqueIdForMethod(UniqueId containerId, Class testClass, String methodName) { return containerId.append(VintageTestDescriptor.SEGMENT_TYPE_TEST, methodValue(testClass, methodName)); } public static UniqueId engineId() { return UniqueId.forEngine(VintageTestDescriptor.ENGINE_ID); } } junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/descriptor/000077500000000000000000000000001455764576500307455ustar00rootroot00000000000000DescriptionUtilsTests.java000066400000000000000000000044541455764576500360670ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.stream.Stream; import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.platform.commons.util.ClassFilter; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.runner.Description; import org.junit.vintage.engine.discovery.IsPotentialJUnit4TestClass; class DescriptionUtilsTests { @SuppressWarnings("deprecation") AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(true); @TestFactory Stream computedMethodNameCorrectly() { var classFilter = ClassFilter.of(new IsPotentialJUnit4TestClass()); var testClasses = ReflectionUtils.findAllClassesInPackage("org.junit.vintage.engine.samples", classFilter); return testClasses.stream().flatMap(this::toDynamicTests); } private Stream toDynamicTests(Class testClass) { try { var runner = builder.runnerForClass(testClass); return toDynamicTests(Stream.of(runner.getDescription())); } catch (Throwable throwable) { throw new RuntimeException(throwable); } } Stream toDynamicTests(Stream children) { return children.map(description -> description.isTest() // ? toDynamicTest(description, "child: " + description.toString()) // : dynamicContainer("class: " + description.toString(), Stream.concat( // Stream.of(toDynamicTest(description, "self")), // toDynamicTests(description.getChildren().stream())))); } private DynamicTest toDynamicTest(Description description, String displayName) { return dynamicTest(displayName, () -> assertEquals(description.getMethodName(), DescriptionUtils.getMethodName(description))); } } OrFilterTests.java000066400000000000000000000044161455764576500343070ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.List; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; /** * @since 5.5 */ class OrFilterTests { @Test void exceptionWithoutAnyFilters() { var actual = assertThrows(PreconditionViolationException.class, () -> new OrFilter(Set.of())); assertEquals("filters must not be empty", actual.getMessage()); } @Test void evaluatesSingleFilter() { var filter = mockFilter("foo", true); var orFilter = new OrFilter(Set.of(filter)); assertEquals("foo", orFilter.describe()); var description = Description.createTestDescription(getClass(), "evaluatesSingleFilter"); assertTrue(orFilter.shouldRun(description)); verify(filter).shouldRun(same(description)); } @Test void evaluatesMultipleFilters() { var filter1 = mockFilter("foo", false); var filter2 = mockFilter("bar", true); var orFilter = new OrFilter(List.of(filter1, filter2)); assertEquals("foo OR bar", orFilter.describe()); var description = Description.createTestDescription(getClass(), "evaluatesMultipleFilters"); assertTrue(orFilter.shouldRun(description)); verify(filter1).shouldRun(same(description)); verify(filter2).shouldRun(same(description)); } private Filter mockFilter(String description, boolean result) { var filter = mock(Filter.class); when(filter.describe()).thenReturn(description); when(filter.shouldRun(any())).thenReturn(result); return filter; } } TestSourceProviderTests.java000066400000000000000000000022561455764576500363740ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.runner.Description; import org.junit.vintage.engine.samples.junit4.ConcreteJUnit4TestCase; /** * @since 5.6 */ class TestSourceProviderTests { @Test void findsInheritedMethod() { var description = Description.createTestDescription(ConcreteJUnit4TestCase.class, "theTest"); var source = new TestSourceProvider().findTestSource(description); assertThat(source).isInstanceOf(MethodSource.class); var methodSource = (MethodSource) source; assertEquals(ConcreteJUnit4TestCase.class.getName(), methodSource.getClassName()); assertEquals("theTest", methodSource.getMethodName()); } } VintageTestDescriptorTests.java000066400000000000000000000033561455764576500370570ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.junit.platform.engine.UniqueId; import org.junit.runner.Description; import org.junit.vintage.engine.samples.junit4.ConcreteJUnit4TestCase; class VintageTestDescriptorTests { private static final UniqueId uniqueId = UniqueId.forEngine("vintage"); @Test void legacyReportingNameUsesClassName() { var description = Description.createSuiteDescription(ConcreteJUnit4TestCase.class); var testDescriptor = new VintageTestDescriptor(uniqueId, description, null); assertEquals("org.junit.vintage.engine.samples.junit4.ConcreteJUnit4TestCase", testDescriptor.getLegacyReportingName()); } @Test void legacyReportingNameUsesMethodName() { var description = Description.createTestDescription(ConcreteJUnit4TestCase.class, "legacyTest"); var testDescriptor = new VintageTestDescriptor(uniqueId, description, null); assertEquals("legacyTest", testDescriptor.getLegacyReportingName()); } @Test void legacyReportingNameFallbackToDisplayName() { var suiteName = "Legacy Suite"; var description = Description.createSuiteDescription(suiteName); var testDescriptor = new VintageTestDescriptor(uniqueId, description, null); assertEquals(testDescriptor.getDisplayName(), testDescriptor.getLegacyReportingName()); assertEquals(suiteName, testDescriptor.getLegacyReportingName()); } } junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/discovery/000077500000000000000000000000001455764576500305765ustar00rootroot00000000000000IsPotentialJUnit4TestClassTests.java000066400000000000000000000024261455764576500375300ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; class IsPotentialJUnit4TestClassTests { private final IsPotentialJUnit4TestClass isPotentialJUnit4TestClass = new IsPotentialJUnit4TestClass(); @Test void staticMemberClass() { assertTrue(isPotentialJUnit4TestClass.test(Foo.class)); } public static class Foo { } @Test void nonPublicClass() { assertFalse(isPotentialJUnit4TestClass.test(Bar.class)); } static class Bar { } @Test void abstractClass() { assertFalse(isPotentialJUnit4TestClass.test(Baz.class)); } public static abstract class Baz { } @Test void anonymousClass() { var foo = new Foo() { }; assertFalse(isPotentialJUnit4TestClass.test(foo.getClass())); } public class FooBaz { } @Test void publicInnerClass() { assertFalse(isPotentialJUnit4TestClass.test(FooBaz.class)); } } RunnerTestDescriptorPostProcessorTests.java000066400000000000000000000063211455764576500413250ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.mockito.Mockito.mock; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.vintage.engine.VintageUniqueIdBuilder; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.samples.junit4.IgnoredJUnit4TestCase; import org.junit.vintage.engine.samples.junit4.IgnoredJUnit4TestCaseWithNotFilterableRunner; import org.junit.vintage.engine.samples.junit4.NotFilterableRunner; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods; /** * Tests for {@link RunnerTestDescriptorPostProcessor}. * * @since 5.5 */ @TrackLogRecords class RunnerTestDescriptorPostProcessorTests { @Test void doesNotLogAnythingForFilterableRunner(LogRecordListener listener) { resolve(selectMethod(PlainJUnit4TestCaseWithFiveTestMethods.class, "successfulTest")); assertThat(listener.stream(RunnerTestDescriptor.class)).isEmpty(); } @Test void doesNotLogAnythingForNonFilterableRunnerIfNoFiltersAreToBeApplied(LogRecordListener listener) { resolve(selectClass(IgnoredJUnit4TestCase.class)); assertThat(listener.stream(RunnerTestDescriptor.class)).isEmpty(); } @Test void logsWarningOnNonFilterableRunner(LogRecordListener listener) { Class testClass = IgnoredJUnit4TestCaseWithNotFilterableRunner.class; resolve(selectMethod(testClass, "someTest")); // @formatter:off assertThat(listener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) .containsOnlyOnce("Runner " + NotFilterableRunner.class.getName() + " (used on class " + testClass.getName() + ") does not support filtering" + " and will therefore be run completely."); // @formatter:on } private void resolve(DiscoverySelector selector) { var request = LauncherDiscoveryRequestBuilder.request().selectors(selector).listeners( mock(LauncherDiscoveryListener.class)).build(); TestDescriptor engineDescriptor = new VintageDiscoverer().discover(request, VintageUniqueIdBuilder.engineId()); var runnerTestDescriptor = (RunnerTestDescriptor) getOnlyElement(engineDescriptor.getChildren()); new RunnerTestDescriptorPostProcessor().applyFiltersAndCreateDescendants(runnerTestDescriptor); } } VintageDiscovererTests.java000066400000000000000000000114601455764576500360320ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.SelectorResolutionResult.Status.FAILED; import static org.junit.platform.engine.SelectorResolutionResult.Status.UNRESOLVED; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.vintage.engine.VintageUniqueIdBuilder.engineId; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import java.util.function.Consumer; import org.junit.jupiter.api.Test; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.vintage.engine.VintageUniqueIdBuilder; import org.junit.vintage.engine.samples.junit3.AbstractJUnit3TestCase; import org.junit.vintage.engine.samples.junit4.AbstractJunit4TestCaseWithConstructorParameter; import org.mockito.ArgumentCaptor; /** * Tests for {@link VintageDiscoverer}. * * @since 4.12 */ class VintageDiscovererTests { @Test void classNameFilterExcludesClass() { // @formatter:off EngineDiscoveryRequest request = request() .selectors(selectClass(Foo.class), selectClass(Bar.class)) .filters(ClassNameFilter.includeClassNamePatterns(".*Foo")) .build(); // @formatter:on var testDescriptor = discover(request); assertThat(testDescriptor.getChildren()).hasSize(1); assertThat(getOnlyElement(testDescriptor.getChildren()).getUniqueId().toString()).contains(Foo.class.getName()); } @Test void packageNameFilterExcludesClasses() { // @formatter:off EngineDiscoveryRequest request = request() .selectors(selectClass(Foo.class), selectClass(Bar.class)) .filters(PackageNameFilter.excludePackageNames("org.junit.vintage.engine.discovery")) .build(); // @formatter:on var testDescriptor = discover(request); assertThat(testDescriptor.getChildren()).isEmpty(); } @Test void doesNotResolveAbstractJUnit3Classes() { doesNotResolve(selectClass(AbstractJUnit3TestCase.class)); } @Test void doesNotResolveAbstractJUnit4Classes() { doesNotResolve(selectClass(AbstractJunit4TestCaseWithConstructorParameter.class)); } @Test void failsToResolveUnloadableTestClass() { var uniqueId = VintageUniqueIdBuilder.uniqueIdForClass("foo.bar.UnknownClass"); doesNotResolve(selectUniqueId(uniqueId), result -> { assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().get()).hasMessageContaining("Unknown class"); }); } @Test void ignoresUniqueIdsOfOtherEngines() { doesNotResolve(selectUniqueId(UniqueId.forEngine("someEngine"))); } private void doesNotResolve(DiscoverySelector selector) { doesNotResolve(selector, result -> assertThat(result.getStatus()).isEqualTo(UNRESOLVED)); } private void doesNotResolve(DiscoverySelector selector, Consumer resultCheck) { var discoveryListener = mock(LauncherDiscoveryListener.class); var request = request() // .selectors(selector) // .listeners(discoveryListener) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .build(); var testDescriptor = discover(request); assertThat(testDescriptor.getChildren()).isEmpty(); var resultCaptor = ArgumentCaptor.forClass(SelectorResolutionResult.class); verify(discoveryListener).selectorProcessed(eq(UniqueId.forEngine("junit-vintage")), eq(selector), resultCaptor.capture()); resultCheck.accept(resultCaptor.getValue()); } private TestDescriptor discover(EngineDiscoveryRequest request) { return new VintageDiscoverer().discover(request, engineId()); } public static class Foo { @org.junit.Test public void test() { } } public static class Bar { @org.junit.Test public void test() { } } } junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/000077500000000000000000000000001455764576500305725ustar00rootroot00000000000000TestRunTests.java000066400000000000000000000051271455764576500340120ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.execution; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.runner.Description.createTestDescription; import static org.junit.vintage.engine.VintageUniqueIdBuilder.engineId; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_DYNAMIC; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER; import org.junit.jupiter.api.Test; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichFails; /** * @since 4.12 */ class TestRunTests { @Test void returnsEmptyOptionalForUnknownDescriptions() throws Exception { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; var runnerId = engineId().append(SEGMENT_TYPE_RUNNER, testClass.getName()); var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass), false); var unknownDescription = createTestDescription(testClass, "dynamicTest"); var testRun = new TestRun(runnerTestDescriptor); var testDescriptor = testRun.lookupNextTestDescriptor(unknownDescription); assertThat(testDescriptor).isEmpty(); } @Test void registersDynamicTestDescriptors() throws Exception { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; var runnerId = engineId().append(SEGMENT_TYPE_RUNNER, testClass.getName()); var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass), false); var dynamicTestId = runnerId.append(SEGMENT_TYPE_DYNAMIC, "dynamicTest"); var dynamicDescription = createTestDescription(testClass, "dynamicTest"); var dynamicTestDescriptor = new VintageTestDescriptor(dynamicTestId, dynamicDescription, null); var testRun = new TestRun(runnerTestDescriptor); testRun.registerDynamicTest(dynamicTestDescriptor); assertThat(testRun.lookupNextTestDescriptor(dynamicDescription)).contains(dynamicTestDescriptor); assertTrue(testRun.isDescendantOfRunnerTestDescriptor(dynamicTestDescriptor)); } } junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/000077500000000000000000000000001455764576500303035ustar00rootroot00000000000000UniqueIdReaderTests.java000066400000000000000000000035401455764576500347620ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.support; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.runner.Description.createTestDescription; import java.util.logging.Level; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; /** * Tests for {@link UniqueIdReader}. * * @since 4.12 */ @TrackLogRecords class UniqueIdReaderTests { @Test void readsUniqueId(LogRecordListener listener) { var description = createTestDescription("ClassName", "methodName", "uniqueId"); var uniqueId = new UniqueIdReader().apply(description); assertEquals("uniqueId", uniqueId); assertThat(listener.stream(UniqueIdReader.class)).isEmpty(); } @Test void returnsDisplayNameWhenUniqueIdCannotBeRead(LogRecordListener listener) { var description = createTestDescription("ClassName", "methodName", "uniqueId"); assertEquals("methodName(ClassName)", description.getDisplayName()); var uniqueId = new UniqueIdReader("wrongFieldName").apply(description); assertEquals(description.getDisplayName(), uniqueId); var logRecord = listener.stream(UniqueIdReader.class, Level.WARNING).findFirst(); assertThat(logRecord).isPresent(); assertThat(logRecord.get().getMessage()).isEqualTo( "Could not read unique ID for Description; using display name instead: " + description.getDisplayName()); assertThat(logRecord.get().getThrown()).isInstanceOf(NoSuchFieldException.class); } } UniqueIdStringifierTests.java000066400000000000000000000051531455764576500360470ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.support; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.ByteArrayInputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.Base64; import org.junit.jupiter.api.Test; /** * @since 4.12 */ class UniqueIdStringifierTests { @Test void returnsReadableStringForKnownTypes() { var stringifier = new UniqueIdStringifier(); assertEquals("foo", stringifier.apply("foo")); assertEquals("42", stringifier.apply(42)); assertEquals("42", stringifier.apply(42L)); assertEquals("42.23", stringifier.apply(42.23d)); } @Test void serializesUnknownTypes() throws Exception { var stringifier = new UniqueIdStringifier(); var serialized = stringifier.apply(new MyCustomId(42)); var deserializedObject = deserialize(decodeBase64(serialized)); assertThat(deserializedObject).isInstanceOf(MyCustomId.class); assertEquals(42, ((MyCustomId) deserializedObject).getValue()); } @Test void usesToStringWhenSerializationFails() { var stringifier = new UniqueIdStringifier(); var serialized = stringifier.apply(new ClassWithErroneousSerialization()); var deserializedString = new String(decodeBase64(serialized), UniqueIdStringifier.CHARSET); assertEquals("value from toString()", deserializedString); } private byte[] decodeBase64(String value) { return Base64.getDecoder().decode(value.getBytes(UniqueIdStringifier.CHARSET)); } private Object deserialize(byte[] bytes) throws Exception { try (var inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes))) { return inputStream.readObject(); } } private static class MyCustomId implements Serializable { private static final long serialVersionUID = 1L; private final int value; MyCustomId(int value) { this.value = value; } int getValue() { return value; } } private static class ClassWithErroneousSerialization implements Serializable { private static final long serialVersionUID = 1L; Object writeReplace() throws ObjectStreamException { throw new InvalidObjectException("failed on purpose"); } @Override public String toString() { return "value from toString()"; } } } junit5-r5.10.2/junit-vintage-engine/src/test/resources/000077500000000000000000000000001455764576500230365ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/test/resources/log4j2-test.xml000066400000000000000000000010571455764576500256410ustar00rootroot00000000000000 junit5-r5.10.2/junit-vintage-engine/src/test/resources/vintage-testjar.jar000066400000000000000000000020321455764576500266400ustar00rootroot00000000000000PK y"Jcom/UT `jXGjXux PK y"J com/example/UT `jXGjXux PK o"Jcom/example/project/UT 1jXGjXux PKy"J'RntQ$com/example/project/JUnit4Test.classUT `jX`jXux }QN0P(ʣ;zH $`QUxLqؽ-V |81A +9ϙc+ovk"2VhVP9PZCV|l$C<˒ע31ª|_eRNd.D2%Z3 ޽ϕ L;ȮJ%imphJ烌\pW&?]FTZjDL vVϥ:E;N/`ϾRxio !,K޼ yEy+kEJ1|4 6",~PK y"JAcom/UT`jXux PK y"J A>com/example/UT`jXux PK o"JAcom/example/project/UT1jXux PKy"J'RntQ$com/example/project/JUnit4Test.classUT`jXux PK`junit5-r5.10.2/junit-vintage-engine/src/testFixtures/000077500000000000000000000000001455764576500225565ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/000077500000000000000000000000001455764576500241035ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/000077500000000000000000000000001455764576500246725ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/000077500000000000000000000000001455764576500260235ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/vintage/000077500000000000000000000000001455764576500274605ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/vintage/engine/000077500000000000000000000000001455764576500307255ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/vintage/engine/samples/000077500000000000000000000000001455764576500323715ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/vintage/engine/samples/spock/000077500000000000000000000000001455764576500335105ustar00rootroot00000000000000SpockTestCaseWithUnrolledAndRegularFeatureMethods.groovy000066400000000000000000000006001455764576500465550ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/groovy/org/junit/vintage/engine/samples/spockpackage org.junit.vintage.engine.samples.spock import spock.lang.Specification import spock.lang.Unroll class SpockTestCaseWithUnrolledAndRegularFeatureMethods extends Specification { @Unroll def "unrolled feature for #input"() { expect: input == 42 where: input << [23, 42] } def "regular"() { expect: true } } junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/000077500000000000000000000000001455764576500234775ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/000077500000000000000000000000001455764576500242665ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/000077500000000000000000000000001455764576500254175ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/000077500000000000000000000000001455764576500270545ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/000077500000000000000000000000001455764576500303215ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/000077500000000000000000000000001455764576500317655ustar00rootroot00000000000000PlainOldJavaClassWithoutAnyTestsTestCase.java000066400000000000000000000007441455764576500425630ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples; /** * @since 4.12 */ public class PlainOldJavaClassWithoutAnyTestsTestCase { public void doSomething() { // no-op } } junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/000077500000000000000000000000001455764576500332015ustar00rootroot00000000000000AbstractJUnit3TestCase.java000066400000000000000000000011131455764576500402150ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.framework.TestCase; import org.junit.Assert; /** * @since 4.12 */ public abstract class AbstractJUnit3TestCase extends TestCase { public void test() { Assert.fail("this test should not be run"); } } IgnoredJUnit3TestCase.java000066400000000000000000000011551455764576500400470ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Ignore; /** * @since 4.12 */ @Ignore("testing") public class IgnoredJUnit3TestCase extends TestCase { public void test() { Assert.fail("this test should be ignored"); } } JUnit3ParallelSuiteWithSubsuites.java000066400000000000000000000021101455764576500423250ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.extensions.ActiveTestSuite; import junit.framework.TestCase; import junit.framework.TestSuite; public class JUnit3ParallelSuiteWithSubsuites extends TestCase { private final String arg; public JUnit3ParallelSuiteWithSubsuites(String name, String arg) { super(name); this.arg = arg; } public void hello() { assertNotNull(arg); } public static TestSuite suite() { TestSuite root = new ActiveTestSuite("allTests"); var case1 = new TestSuite("Case1"); case1.addTest(new JUnit3ParallelSuiteWithSubsuites("hello", "world")); root.addTest(case1); var case2 = new TestSuite("Case2"); case2.addTest(new JUnit3ParallelSuiteWithSubsuites("hello", "WORLD")); root.addTest(case2); return root; } } JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails.java000066400000000000000000000013131455764576500463430ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.framework.TestCase; import junit.framework.TestSuite; /** * @since 4.12 */ public class JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails extends TestCase { public static junit.framework.Test suite() { var suite = new TestSuite(); suite.addTestSuite(PlainJUnit3TestCaseWithSingleTestWhichFails.class); return suite; } } JUnit3SuiteWithSubsuites.java000066400000000000000000000017631455764576500406650ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.framework.TestCase; import junit.framework.TestSuite; public class JUnit3SuiteWithSubsuites extends TestCase { private final String arg; public JUnit3SuiteWithSubsuites(String name, String arg) { super(name); this.arg = arg; } public void hello() { assertNotNull(arg); } public static TestSuite suite() { var root = new TestSuite("allTests"); var case1 = new TestSuite("Case1"); case1.addTest(new JUnit3SuiteWithSubsuites("hello", "world")); root.addTest(case1); var case2 = new TestSuite("Case2"); case2.addTest(new JUnit3SuiteWithSubsuites("hello", "WORLD")); root.addTest(case2); return root; } } JUnit4SuiteWithIgnoredJUnit3TestCase.java000066400000000000000000000011271455764576500427520ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ IgnoredJUnit3TestCase.class }) public class JUnit4SuiteWithIgnoredJUnit3TestCase { } PlainJUnit3TestCaseWithSingleTestWhichFails.java000066400000000000000000000011211455764576500443140ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit3/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit3; import junit.framework.TestCase; import org.junit.Assert; /** * @since 4.12 */ public class PlainJUnit3TestCaseWithSingleTestWhichFails extends TestCase { public void test() { Assert.fail("this test should fail"); } } junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/000077500000000000000000000000001455764576500332025ustar00rootroot00000000000000AbstractJUnit4TestCase.java000066400000000000000000000007331455764576500402260ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Test; public abstract class AbstractJUnit4TestCase { @Test public void theTest() { } } AbstractJunit4TestCaseWithConstructorParameter.java000066400000000000000000000010741455764576500452300ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Test; public abstract class AbstractJunit4TestCaseWithConstructorParameter { public AbstractJunit4TestCaseWithConstructorParameter(int parameter) { } @Test public void test() { } } Categories.java000066400000000000000000000011331455764576500360510ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; /** * @since 4.12 */ public class Categories { public interface Plain { } public interface Failing { } public interface Skipped { } public interface SkippedWithReason extends Skipped { } public interface Successful { } } CompletelyDynamicTestCase.java000066400000000000000000000012061455764576500410430ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.vintage.engine.samples.junit4.ConfigurableRunner.ChildCount; /** * Simulates a Spock 1.x test with only {@code @Unroll} feature methods. */ @RunWith(DynamicRunner.class) @ChildCount(1) public class CompletelyDynamicTestCase { } ConcreteJUnit4TestCase.java000066400000000000000000000006641455764576500402300ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; public class ConcreteJUnit4TestCase extends AbstractJUnit4TestCase { } ConfigurableRunner.java000066400000000000000000000035411455764576500375630ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static java.util.stream.IntStream.range; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.junit.runner.Description; import org.junit.runner.Runner; import org.junit.runner.notification.RunNotifier; /** * @since 5.1 */ abstract class ConfigurableRunner extends Runner { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ChildCount { int value(); } protected final Class testClass; protected final List filteredChildren = new ArrayList<>(); ConfigurableRunner(Class testClass) { this.testClass = testClass; var childCountAnnotation = testClass.getAnnotation(ChildCount.class); int childCount = Optional.ofNullable(childCountAnnotation).map(ChildCount::value).orElse(0); // @formatter:off range(0, childCount) .mapToObj(index -> Description.createTestDescription(testClass, "Test #" + index)) .forEach(filteredChildren::add); // @formatter:on } @Override public Description getDescription() { var suiteDescription = Description.createSuiteDescription(testClass); filteredChildren.forEach(suiteDescription::addChild); return suiteDescription; } @Override public void run(RunNotifier notifier) { filteredChildren.forEach(child -> { notifier.fireTestStarted(child); notifier.fireTestFinished(child); }); } } DynamicRunner.java000066400000000000000000000020171455764576500365440ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import org.junit.runner.manipulation.Filterable; import org.junit.runner.manipulation.NoTestsRemainException; public class DynamicRunner extends ConfigurableRunner implements Filterable { public DynamicRunner(Class testClass) { super(testClass); } @Override public Description getDescription() { return Description.createSuiteDescription(testClass); } @Override public void filter(Filter filter) throws NoTestsRemainException { filteredChildren.removeIf(each -> !filter.shouldRun(each)); if (filteredChildren.isEmpty()) { throw new NoTestsRemainException(); } } } EmptyIgnoredTestCase.java000066400000000000000000000006761455764576500400410ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Ignore; @Ignore("empty") public class EmptyIgnoredTestCase { } EnclosedJUnit4TestCase.java000066400000000000000000000016731455764576500402230ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; /** * @since 4.12 */ @RunWith(Enclosed.class) public class EnclosedJUnit4TestCase { @Category(Categories.Plain.class) public static class NestedClass { @Test @Category(Categories.Failing.class) public void failingTest() { fail("this test should fail"); } @Test public void successfulTest() { assertEquals(3, 1 + 2); } } } EnclosedWithParameterizedChildrenJUnit4TestCase.java000066400000000000000000000026321455764576500452410ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; // Source: https://github.com/junit-team/junit5/issues/3083 @RunWith(Enclosed.class) public class EnclosedWithParameterizedChildrenJUnit4TestCase { @RunWith(Parameterized.class) public static class NestedTestCase1 { @Parameters public static Collection data() { return Arrays.asList(new Object[] { 1, 2 }, new Object[] { 3, 4 }); } @SuppressWarnings("unused") public NestedTestCase1(final int a, final int b) { } @Test public void test() { } } @RunWith(Parameterized.class) public static class NestedTestCase2 { @Parameters public static Collection data() { return Arrays.asList(new Object[] { 1, 2 }, new Object[] { 3, 4 }); } @SuppressWarnings("unused") public NestedTestCase2(final int a, final int b) { } @Test public void test() { } } } ExceptionThrowingRunner.java000066400000000000000000000013431455764576500406410ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.notification.RunNotifier; /** * @since 4.12 */ public class ExceptionThrowingRunner extends ConfigurableRunner { public ExceptionThrowingRunner(Class testClass) { super(testClass); } @Override public void run(RunNotifier notifier) { throw new RuntimeException("Simulated exception in custom runner for " + testClass.getName()); } } IgnoredJUnit4TestCase.java000066400000000000000000000014521455764576500400510ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import static org.junit.runners.MethodSorters.NAME_ASCENDING; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; /** * @since 4.12 */ @Ignore("complete class is ignored") @FixMethodOrder(NAME_ASCENDING) public class IgnoredJUnit4TestCase { @Test public void failingTest() { fail("this test is discovered, but skipped"); } @Test public void succeedingTest() { } } IgnoredJUnit4TestCaseWithNotFilterableRunner.java000066400000000000000000000010211455764576500445420ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Ignore; /** * @since 5.1 */ @Ignore public class IgnoredJUnit4TestCaseWithNotFilterableRunner extends JUnit4TestCaseWithNotFilterableRunner { } IgnoredParameterizedTestCase.java000066400000000000000000000016261455764576500415330ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import java.util.List; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; /** * @since 5.4.1 */ @RunWith(Parameterized.class) public class IgnoredParameterizedTestCase { @Parameters(name = "{0}") public static Iterable parameters() { return List.of("foo", "bar"); } @Parameter public String value; @Test @Ignore public void test() { // never called } } JUnit4ParameterizedTestCase.java000066400000000000000000000021451455764576500412560ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; /** * Test case used in {@link JUnit4ParameterizedTests}. * * @since 4.12 */ @RunWith(Parameterized.class) public class JUnit4ParameterizedTestCase { @Parameters public static Object[] data() { return new Object[] { 1, 2, 3 }; } public JUnit4ParameterizedTestCase(int i) { } @Test public void test1() { fail("this test should fail"); } @Test public void endingIn_test1() { fail("this test should fail"); } @Test public void test1_atTheBeginning() { fail("this test should fail"); } @Test public void test2() { /* always succeeds */ } } JUnit4SuiteOfSuiteWithFilterableChildRunner.java000066400000000000000000000012001455764576500443710ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 5.1 */ @RunWith(Suite.class) @SuiteClasses(JUnit4TestCaseWithNotFilterableRunner.class) public class JUnit4SuiteOfSuiteWithFilterableChildRunner { } JUnit4SuiteOfSuiteWithIgnoredJUnit4TestCase.java000066400000000000000000000012001455764576500442430ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit4SuiteWithIgnoredJUnit4TestCase.class) public class JUnit4SuiteOfSuiteWithIgnoredJUnit4TestCase { } JUnit4SuiteOfSuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass.java000066400000000000000000000012661455764576500515760ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit4SuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass.class) public class JUnit4SuiteOfSuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass { } JUnit4SuiteOfSuiteWithJUnit4TestCaseWithErrorInBeforeClass.java000066400000000000000000000012361455764576500472120ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass.class) public class JUnit4SuiteOfSuiteWithJUnit4TestCaseWithErrorInBeforeClass { } JUnit4SuiteWithExceptionThrowingRunner.java000066400000000000000000000011431455764576500435430ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.vintage.engine.samples.junit4.ConfigurableRunner.ChildCount; /** * @since 4.12 */ @RunWith(ExceptionThrowingRunner.class) @ChildCount(1) public class JUnit4SuiteWithExceptionThrowingRunner { } JUnit4SuiteWithIgnoredJUnit4TestCase.java000066400000000000000000000011521455764576500427520ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(IgnoredJUnit4TestCase.class) public class JUnit4SuiteWithIgnoredJUnit4TestCase { } JUnit4SuiteWithJUnit3SuiteWithSingleTestCase.java000066400000000000000000000013701455764576500444530ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails.class) public class JUnit4SuiteWithJUnit3SuiteWithSingleTestCase { } JUnit4SuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass.java000066400000000000000000000012401455764576500502670ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit4TestCaseWithAssumptionFailureInBeforeClass.class) public class JUnit4SuiteWithJUnit4TestCaseWithAssumptionFailureInBeforeClass { } JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass.java000066400000000000000000000012101455764576500457030ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(JUnit4TestCaseWithErrorInBeforeClass.class) public class JUnit4SuiteWithJUnit4TestCaseWithErrorInBeforeClass { } JUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.java000066400000000000000000000013401455764576500532340ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.class, PlainJUnit4TestCaseWithSingleTestWhichFails.class }) public class JUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished { } JUnit4SuiteWithJUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java000066400000000000000000000012651455764576500523100ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 5.6.2 */ @RunWith(Suite.class) @SuiteClasses(JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.class) public class JUnit4SuiteWithJUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames { } JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored.java000066400000000000000000000012361455764576500500560ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses(PlainJUnit4TestCaseWithSingleTestWhichIsIgnored.class) public class JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored { } JUnit4SuiteWithTwoTestCases.java000066400000000000000000000012501455764576500412600ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @since 4.12 */ @RunWith(Suite.class) @SuiteClasses({ PlainJUnit4TestCaseWithTwoTestMethods.class, PlainJUnit4TestCaseWithSingleTestWhichFails.class }) public class JUnit4SuiteWithTwoTestCases { } JUnit4TestCaseWithAssumptionFailureInBeforeClass.java000066400000000000000000000014261455764576500453710ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.AssumptionViolatedException; import org.junit.BeforeClass; import org.junit.Test; /** * @since 4.12 */ public class JUnit4TestCaseWithAssumptionFailureInBeforeClass { @BeforeClass public static void failingBeforeClass() { throw new AssumptionViolatedException("assumption violated"); } @Test public void test() { fail("this should never be called"); } } JUnit4TestCaseWithDistinguishableOverloadedMethod.java000066400000000000000000000014031455764576500455760ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.experimental.theories.Theories; import org.junit.runner.RunWith; /** * @since 5.5 */ @RunWith(Theories.class) public class JUnit4TestCaseWithDistinguishableOverloadedMethod { @Test public void test() { test("foo"); } @SuppressWarnings("SameParameterValue") private void test(String message) { fail(message); } } JUnit4TestCaseWithErrorCollectorStoringMultipleFailures.java000066400000000000000000000020451455764576500470320ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.StringContains.containsString; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ErrorCollector; public class JUnit4TestCaseWithErrorCollectorStoringMultipleFailures { @Rule public ErrorCollector collector = new ErrorCollector(); @Test public void example() { collector.addError(new Throwable("first thing went wrong")); collector.addError(new Throwable("second thing went wrong")); collector.checkThat(getResult(), not(containsString("ERROR!"))); // all lines will run, and then a combined failure logged at the end. } private String getResult() { return "This is an ERROR!"; } } JUnit4TestCaseWithErrorInAfterClass.java000066400000000000000000000015511455764576500426460ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import static org.junit.runners.MethodSorters.NAME_ASCENDING; import org.junit.AfterClass; import org.junit.FixMethodOrder; import org.junit.Test; /** * @since 4.12 */ @FixMethodOrder(NAME_ASCENDING) public class JUnit4TestCaseWithErrorInAfterClass { @AfterClass public static void failingAfterClass() { fail("error in @AfterClass"); } @Test public void failingTest() { fail("expected to fail"); } @Test public void succeedingTest() { // no-op } } JUnit4TestCaseWithErrorInBeforeClass.java000066400000000000000000000012741455764576500430110ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.BeforeClass; import org.junit.Test; /** * @since 4.12 */ public class JUnit4TestCaseWithErrorInBeforeClass { @BeforeClass public static void failingBeforeClass() { fail("something went wrong"); } @Test public void test() { fail("this should never be called"); } } JUnit4TestCaseWithExceptionThrowingRunner.java000066400000000000000000000011461455764576500441700ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.RunWith; import org.junit.vintage.engine.samples.junit4.ConfigurableRunner.ChildCount; /** * @since 4.12 */ @RunWith(ExceptionThrowingRunner.class) @ChildCount(0) public class JUnit4TestCaseWithExceptionThrowingRunner { } JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished.java000066400000000000000000000012141455764576500503300ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(RunnerThatOnlyReportsFailures.class) public class JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished { @Test public void testWithMissingEvents() { fail("boom"); } } JUnit4TestCaseWithIndistinguishableOverloadedMethod.java000066400000000000000000000016511455764576500461320ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.experimental.theories.DataPoint; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; /** * @since 4.12 */ @RunWith(Theories.class) public class JUnit4TestCaseWithIndistinguishableOverloadedMethod { @DataPoint public static int MAGIC_NUMBER = 42; @Theory public void theory(int i) { fail("failing theory with single parameter"); } @Theory public void theory(int i, int j) { fail("failing theory with two parameters"); } } JUnit4TestCaseWithNotFilterableRunner.java000066400000000000000000000013641455764576500432440ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.vintage.engine.samples.junit4.ConfigurableRunner.ChildCount; /** * @since 5.1 */ @RunWith(NotFilterableRunner.class) @ChildCount(2) @Category(Categories.Successful.class) public class JUnit4TestCaseWithNotFilterableRunner { @Test public void someTest() { } } JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java000066400000000000000000000015341455764576500474030ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; /** * @since 4.12 */ @Label("(TestClass)") @RunWith(RunnerWithCustomUniqueIdsAndDisplayNames.class) public class JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames { @Test @Label("(TestMethod)") public void test() { Assert.fail(); } } @Retention(RUNTIME) @interface Label { String value(); } JUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions.java000066400000000000000000000032501455764576500502460ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.Description; import org.junit.runner.RunWith; import org.junit.runner.notification.RunNotifier; @RunWith(JUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions.Runner.class) public class JUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions { public static class Runner extends org.junit.runner.Runner { private final Class testClass; public Runner(Class testClass) { this.testClass = testClass; } @Override public Description getDescription() { var suiteDescription = Description.createSuiteDescription(testClass); suiteDescription.addChild(getContainerDescription("1st")); suiteDescription.addChild(getContainerDescription("2nd")); return suiteDescription; } private Description getContainerDescription(String name) { var parent = Description.createSuiteDescription(name); parent.addChild(getLeafDescription()); parent.addChild(getLeafDescription()); return parent; } private Description getLeafDescription() { return Description.createTestDescription(testClass, "leaf"); } @Override public void run(RunNotifier notifier) { for (var i = 0; i < 2; i++) { notifier.fireTestIgnored(getLeafDescription()); notifier.fireTestStarted(getLeafDescription()); notifier.fireTestFinished(getLeafDescription()); } } } } MalformedJUnit4TestCase.java000066400000000000000000000012111455764576500403610ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.Test; /** * @since 4.12 */ public class MalformedJUnit4TestCase { @Test @SuppressWarnings("TestMethodWithIncorrectSignature") // intentionally not public void nonPublicTest() { fail("this should never be called"); } } NotFilterableRunner.java000066400000000000000000000010161455764576500377100ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; /** * @since 5.1 */ public class NotFilterableRunner extends ConfigurableRunner { public NotFilterableRunner(Class testClass) { super(testClass); } } ParameterizedTestCase.java000066400000000000000000000016461455764576500402250ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; /** * @since 4.12 */ @RunWith(Parameterized.class) public class ParameterizedTestCase { @Parameters(name = "{0}") public static Iterable parameters() { return List.of("foo", "bar"); } @Parameter public String value; @Test public void test() { assertEquals("foo", value); } } ParameterizedTimingTestCase.java000066400000000000000000000032411455764576500413660ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import java.time.Instant; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.AfterParam; import org.junit.runners.Parameterized.BeforeParam; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; /** * @since 5.9 */ @RunWith(Parameterized.class) public class ParameterizedTimingTestCase { public static Map EVENTS = new LinkedHashMap<>(); @BeforeClass public static void beforeClass() throws Exception { EVENTS.clear(); } @BeforeParam public static void beforeParam(String param) throws Exception { EVENTS.put("beforeParam(" + param + ")", Instant.now()); Thread.sleep(100); } @AfterParam public static void afterParam(String param) throws Exception { Thread.sleep(100); System.out.println("ParameterizedTimingTestCase.afterParam"); EVENTS.put("afterParam(" + param + ")", Instant.now()); } @Parameters(name = "{0}") public static Iterable parameters() { return List.of("foo", "bar"); } @Parameter public String value; @Test public void test() { assertEquals("foo", value); } } ParameterizedWithAfterParamFailureTestCase.java000066400000000000000000000021201455764576500443200ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.AfterParam; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; /** * @since 5.9 */ @RunWith(Parameterized.class) public class ParameterizedWithAfterParamFailureTestCase { @AfterParam public static void afterParam() { fail(); } @Parameters(name = "{0}") public static Iterable parameters() { return List.of("foo", "bar"); } @Parameter public String value; @Test public void test() { assertEquals("foo", value); } } ParameterizedWithBeforeParamFailureTestCase.java000066400000000000000000000021241455764576500444650ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.BeforeParam; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; /** * @since 5.9 */ @RunWith(Parameterized.class) public class ParameterizedWithBeforeParamFailureTestCase { @BeforeParam public static void beforeParam() { fail(); } @Parameters(name = "{0}") public static Iterable parameters() { return List.of("foo", "bar"); } @Parameter public String value; @Test public void test() { assertEquals("foo", value); } } PlainJUnit4TestCaseWithFiveTestMethods.java000066400000000000000000000031521455764576500433560ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; import static org.junit.runners.MethodSorters.NAME_ASCENDING; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.vintage.engine.samples.junit4.Categories.Failing; import org.junit.vintage.engine.samples.junit4.Categories.Plain; import org.junit.vintage.engine.samples.junit4.Categories.Skipped; import org.junit.vintage.engine.samples.junit4.Categories.SkippedWithReason; /** * @since 4.12 */ @FixMethodOrder(NAME_ASCENDING) @Category(Plain.class) public class PlainJUnit4TestCaseWithFiveTestMethods { @Test public void abortedTest() { assumeFalse("this test should be aborted", true); } @Test @Category(Failing.class) public void failingTest() { fail("this test should fail"); } @Test @Ignore @Category(Skipped.class) public void ignoredTest1_withoutReason() { fail("this should never be called"); } @Test @Ignore("a custom reason") @Category(SkippedWithReason.class) public void ignoredTest2_withReason() { fail("this should never be called"); } @Test public void successfulTest() { assertEquals(3, 1 + 2); } } PlainJUnit4TestCaseWithLifecycleMethods.java000066400000000000000000000026231455764576500435260ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class PlainJUnit4TestCaseWithLifecycleMethods { public static final List EVENTS = new ArrayList<>(); @BeforeClass public static void beforeClass() { EVENTS.add("beforeClass"); } @Before public void before() { EVENTS.add("before"); } @Test public void failingTest() { EVENTS.add("failingTest"); fail(); } @Test @Ignore("skipped") public void skippedTest() { EVENTS.add("this should never ever be executed because the test is skipped"); } @Test public void succeedingTest() { EVENTS.add("succeedingTest"); } @After public void after() { EVENTS.add("after"); } @AfterClass public static void afterClass() { EVENTS.add("afterClass"); } } PlainJUnit4TestCaseWithSingleInheritedTestWhichFails.java000066400000000000000000000007761455764576500461710ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; /** * @since 4.12 */ public class PlainJUnit4TestCaseWithSingleInheritedTestWhichFails extends PlainJUnit4TestCaseWithSingleTestWhichFails { } PlainJUnit4TestCaseWithSingleTestWhichFails.java000066400000000000000000000011111455764576500443150ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.fail; import org.junit.Test; /** * @since 4.12 */ public class PlainJUnit4TestCaseWithSingleTestWhichFails { @Test public void failingTest() { fail("this test should fail"); } } PlainJUnit4TestCaseWithSingleTestWhichIsIgnored.java000066400000000000000000000011751455764576500451540ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; /** * @since 4.12 */ public class PlainJUnit4TestCaseWithSingleTestWhichIsIgnored { @Test @Ignore("ignored test") public void ignoredTest() { Assert.fail("this should not be called"); } } PlainJUnit4TestCaseWithTwoTestMethods.java000066400000000000000000000016171455764576500432420ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.junit.runners.MethodSorters.NAME_ASCENDING; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; /** * @since 4.12 */ @FixMethodOrder(NAME_ASCENDING) public class PlainJUnit4TestCaseWithTwoTestMethods { @Test public void failingTest() { fail("this test should fail"); } @Test @Category(Categories.Successful.class) public void successfulTest() { assertEquals(3, 1 + 2); } } RunnerThatOnlyReportsFailures.java000066400000000000000000000020331455764576500417720ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; public class RunnerThatOnlyReportsFailures extends BlockJUnit4ClassRunner { public RunnerThatOnlyReportsFailures(Class klass) throws InitializationError { super(klass); } @Override protected void runChild(FrameworkMethod method, RunNotifier notifier) { var statement = methodBlock(method); try { statement.evaluate(); } catch (Throwable e) { notifier.fireTestFailure(new Failure(describeChild(method), e)); } } } RunnerWithCustomUniqueIdsAndDisplayNames.java000066400000000000000000000041621455764576500440550ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import static org.junit.runner.Description.createTestDescription; import java.io.Serial; import java.io.Serializable; import java.util.Objects; import java.util.function.Supplier; import org.junit.runner.Description; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.Annotatable; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; /** * @since 4.12 */ public class RunnerWithCustomUniqueIdsAndDisplayNames extends BlockJUnit4ClassRunner { public RunnerWithCustomUniqueIdsAndDisplayNames(Class klass) throws InitializationError { super(klass); } @Override protected String getName() { return getLabel(getTestClass(), super::getName); } @Override protected Description describeChild(FrameworkMethod method) { var testName = testName(method); return createTestDescription(getTestClass().getJavaClass().getName(), testName, new CustomUniqueId(testName)); } @Override protected String testName(FrameworkMethod method) { return getLabel(method, () -> super.testName(method)); } private String getLabel(Annotatable element, Supplier fallback) { var label = element.getAnnotation(Label.class); return label == null ? fallback.get() : label.value(); } private static class CustomUniqueId implements Serializable { @Serial private static final long serialVersionUID = 1L; private final String testName; public CustomUniqueId(String testName) { this.testName = testName; } @Override public boolean equals(Object obj) { if (obj instanceof CustomUniqueId) { var that = (CustomUniqueId) obj; return Objects.equals(this.testName, that.testName); } return false; } @Override public int hashCode() { return testName.hashCode(); } } } SingleFailingTheoryTestCase.java000066400000000000000000000012651455764576500413340ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.Assert; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; /** * @since 4.12 */ @RunWith(Theories.class) public class SingleFailingTheoryTestCase { @Theory public void theory() { Assert.fail("this theory should fail"); } } TestCaseRunWithJUnitPlatformRunner.java000066400000000000000000000012761455764576500427010ustar00rootroot00000000000000junit5-r5.10.2/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.vintage.engine.samples.junit4; import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.SelectClasses; import org.junit.runner.RunWith; /** * @since 4.12 */ @SuppressWarnings("deprecation") @RunWith(JUnitPlatform.class) @SelectClasses(PlainJUnit4TestCaseWithSingleTestWhichFails.class) public class TestCaseRunWithJUnitPlatformRunner { } junit5-r5.10.2/platform-tests/000077500000000000000000000000001455764576500162135ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/platform-tests.gradle.kts000066400000000000000000000062031455764576500231600ustar00rootroot00000000000000import org.gradle.api.tasks.PathSensitivity.NONE import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.internal.os.OperatingSystem plugins { id("junitbuild.java-library-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") alias(libs.plugins.jmh) } dependencies { // --- Things we are testing -------------------------------------------------- testImplementation(projects.junitPlatformCommons) testImplementation(projects.junitPlatformConsole) testImplementation(projects.junitPlatformEngine) testImplementation(projects.junitPlatformJfr) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteCommons) testImplementation(projects.junitPlatformSuiteEngine) // --- Things we are testing with --------------------------------------------- testImplementation(projects.junitPlatformRunner) testImplementation(projects.junitPlatformTestkit) testImplementation(testFixtures(projects.junitPlatformCommons)) testImplementation(testFixtures(projects.junitPlatformEngine)) testImplementation(testFixtures(projects.junitPlatformLauncher)) testImplementation(projects.junitJupiterEngine) testImplementation(libs.apiguardian) testImplementation(libs.jfrunit) { exclude(group = "org.junit.vintage") } testImplementation(libs.joox) testImplementation(libs.openTestReporting.tooling) testImplementation(libs.picocli) testImplementation(libs.bundles.xmlunit) testImplementation(testFixtures(projects.junitJupiterApi)) // --- Test run-time dependencies --------------------------------------------- testRuntimeOnly(projects.junitVintageEngine) testRuntimeOnly(libs.groovy4) { because("`ReflectionUtilsTests.findNestedClassesWithInvalidNestedClassFile` needs it") } // --- https://openjdk.java.net/projects/code-tools/jmh/ ----------------------- jmh(libs.jmh.core) jmh(projects.junitJupiterApi) jmh(libs.junit4) jmhAnnotationProcessor(libs.jmh.generator.annprocess) } jmh { jmhVersion = libs.versions.jmh duplicateClassesStrategy = DuplicatesStrategy.WARN fork = 1 warmupIterations = 1 iterations = 5 } tasks { withType().configureEach { useJUnitPlatform { excludeTags("exclude") } jvmArgs("-Xmx1g") distribution { // Retry in a new JVM on Windows to improve chances of successful retries when // cached resources are used (e.g. in ClasspathScannerTests) retryInSameJvm = !OperatingSystem.current().isWindows } } test { // Additional inputs for remote execution with Test Distribution inputs.dir("src/test/resources").withPathSensitivity(RELATIVE) inputs.file(buildFile).withPathSensitivity(NONE) // for UniqueIdTrackingListenerIntegrationTests } test_4_12 { useJUnitPlatform { includeTags("junit4") } } checkstyleJmh { // use same style rules as defined for tests config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } } eclipse { classpath { plusConfigurations.add(projects.junitPlatformConsole.dependencyProject.configurations["shadowed"]) } } idea { module { scopes["PROVIDED"]!!["plus"]!!.add(projects.junitPlatformConsole.dependencyProject.configurations["shadowed"]) } } junit5-r5.10.2/platform-tests/src/000077500000000000000000000000001455764576500170025ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/000077500000000000000000000000001455764576500175605ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/000077500000000000000000000000001455764576500205015ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/org/000077500000000000000000000000001455764576500212705ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/org/junit/000077500000000000000000000000001455764576500224215ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/org/junit/jupiter/000077500000000000000000000000001455764576500241035ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/org/junit/jupiter/jmh/000077500000000000000000000000001455764576500246615ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/jmh/java/org/junit/jupiter/jmh/AssertionBenchmarks.java000066400000000000000000000024771455764576500315030ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.jmh; import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.openjdk.jmh.annotations.Benchmark; /** * JMH benchmarks for assertions. * * @since 5.1 */ public class AssertionBenchmarks { @Benchmark public void junit4_assertTrue_boolean() { Assert.assertTrue(true); } @Benchmark public void junitJupiter_assertTrue_boolean() { Assertions.assertTrue(true); } @Benchmark public void junit4_assertTrue_String_boolean() { Assert.assertTrue("message", true); } @Benchmark public void junitJupiter_assertTrue_boolean_String() { Assertions.assertTrue(true, "message"); } @Benchmark public void junitJupiter_assertTrue_boolean_Supplier() { Assertions.assertTrue(true, () -> "message"); } @Benchmark public void junitJupiter_assertTrue_BooleanSupplier_String() { Assertions.assertTrue(() -> true, "message"); } @Benchmark public void junitJupiter_assertTrue_BooleanSupplier_Supplier() { Assertions.assertTrue(() -> true, () -> "message"); } } junit5-r5.10.2/platform-tests/src/test/000077500000000000000000000000001455764576500177615ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/000077500000000000000000000000001455764576500207025ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/DefaultPackageTestCase.java000066400000000000000000000012271455764576500260430ustar00rootroot00000000000000 /* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Simple test case that is used to verify proper support for classpath scanning * within the default package. * * @since 1.0 */ @Disabled("Only used reflectively by other tests") class DefaultPackageTestCase { @Test void test() { // do nothing } } junit5-r5.10.2/platform-tests/src/test/java/org/000077500000000000000000000000001455764576500214715ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/000077500000000000000000000000001455764576500226225ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/000077500000000000000000000000001455764576500243045ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/api/000077500000000000000000000000001455764576500250555ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/api/condition/000077500000000000000000000000001455764576500270435ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java000066400000000000000000000040761455764576500312610ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Nested; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; class OSTests { @ParameterizedTest @NullAndEmptySource @ValueSource(strings = { " ", "\t" }) void blankOsNameYieldsNull(String name) { assertNull(OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "!", "?", "✨", "MINIX" }) void unknownOsNameYieldsOTHER(String name) { assertEquals(OS.OTHER, OS.parse(name)); } @Nested class ValidNames { @ParameterizedTest @ValueSource(strings = { "AIX", "Aix", "LaIxOS" }) void aix(String name) { assertEquals(OS.AIX, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "FREEBSD", "FreeBSD" }) void freebsd(String name) { assertEquals(OS.FREEBSD, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "LINUX", "Linux" }) void linux(String name) { assertEquals(OS.LINUX, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "MAC", "mac" }) void mac(String name) { assertEquals(OS.MAC, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "OPENBSD", "OpenBSD" }) void openbsd(String name) { assertEquals(OS.OPENBSD, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "SOLARIS", "SunOS" }) void solaris(String name) { assertEquals(OS.SOLARIS, OS.parse(name)); } @ParameterizedTest @ValueSource(strings = { "WINDOW", "Microsoft Windows [Version 10.?]" }) void windows(String name) { assertEquals(OS.WINDOWS, OS.parse(name)); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/extensions/000077500000000000000000000000001455764576500265035ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/extensions/Heavyweight.java000066400000000000000000000055401455764576500316360ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.extensions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; public class Heavyweight implements ParameterResolver, BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { context.getStore(ExtensionContext.Namespace.GLOBAL).put("once", new CloseableOnlyOnceResource()); } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext context) { return Resource.class.equals(parameterContext.getParameter().getType()); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext context) { var engineContext = context.getRoot(); var store = engineContext.getStore(ExtensionContext.Namespace.GLOBAL); var resource = store.getOrComputeIfAbsent(ResourceValue.class); resource.usages.incrementAndGet(); return resource; } interface Resource { String ID = "org.junit.jupiter.extensions.Heavyweight.Resource"; int usages(); } /** * Demo resource class. * *

The class implements interface {@link CloseableResource} * and interface {@link AutoCloseable} to show and ensure that a single * {@link ResourceValue#close()} method implementation is needed to comply * with both interfaces. */ static class ResourceValue implements Resource, CloseableResource, AutoCloseable { static final AtomicInteger creations = new AtomicInteger(); private final AtomicInteger usages = new AtomicInteger(); @SuppressWarnings("unused") // used via reflection ResourceValue() { // Open long-living resources here. assertEquals(1, creations.incrementAndGet(), "Singleton pattern failure!"); } @Override public void close() { // Close resources here. assertEquals(9, usages.get(), "Usage counter mismatch!"); } @Override public int usages() { return usages.get(); } } private static class CloseableOnlyOnceResource implements CloseableResource { private final AtomicBoolean closed = new AtomicBoolean(); @Override public void close() { assertTrue(closed.compareAndSet(false, true), "already closed!"); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/jupiter/extensions/HeavyweightTests.java000066400000000000000000000051561455764576500326640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.jupiter.extensions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.ResourceLock; /** * Unit tests for {@link org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource} * stored values. * * @since 1.1 */ class HeavyweightTests { @AfterAll static void afterAll() { Heavyweight.ResourceValue.creations.set(0); } @Nested @TestInstance(PER_CLASS) @ExtendWith(Heavyweight.class) @ResourceLock(Heavyweight.Resource.ID) class Alpha { private int mark; @BeforeAll void setMark(Heavyweight.Resource resource) { assertTrue(resource.usages() > 0); mark = resource.usages(); } @TestFactory Stream alpha1(Heavyweight.Resource resource) { return Stream.of(dynamicTest("foo", () -> assertTrue(resource.usages() > 1))); } @Test void alpha2(Heavyweight.Resource resource) { assertTrue(resource.usages() > 1); } @Test void alpha3(Heavyweight.Resource resource) { assertTrue(resource.usages() > 1); } @AfterAll void checkMark(Heavyweight.Resource resource) { assertEquals(mark, resource.usages() - 4); } } @Nested @TestInstance(PER_CLASS) @ExtendWith(Heavyweight.class) @ResourceLock(Heavyweight.Resource.ID) class Beta { private int mark; @BeforeAll void beforeAll(Heavyweight.Resource resource) { assertTrue(resource.usages() > 0); mark = resource.usages(); } @BeforeEach void beforeEach(Heavyweight.Resource resource) { assertTrue(resource.usages() > 1); } @Test void beta(Heavyweight.Resource resource) { assertTrue(resource.usages() > 2); } @AfterAll void afterAll(Heavyweight.Resource resource) { assertEquals(mark, resource.usages() - 3); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/000077500000000000000000000000001455764576500244465ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/AbstractEqualsAndHashCodeTests.java000066400000000000000000000024431455764576500332770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform; import static org.assertj.core.api.Assertions.assertThat; /** * Abstract base class for unit tests that wish to test * {@link Object#equals(Object)} and {@link Object#hashCode()}. * * @since 1.3 */ public abstract class AbstractEqualsAndHashCodeTests { protected final void assertEqualsAndHashCode(T equal1, T equal2, T different) { assertThat(equal1).isNotNull(); assertThat(equal2).isNotNull(); assertThat(different).isNotNull(); assertThat(equal1).isNotSameAs(equal2); assertThat(equal1).isNotNull(); assertThat(equal1).isNotEqualTo(new Object()); assertThat(equal1).isNotEqualTo(different); assertThat(different).isNotEqualTo(equal1); assertThat(different).isNotEqualTo(equal2); assertThat(equal1.hashCode()).isNotEqualTo(different.hashCode()); assertThat(equal1).isEqualTo(equal1); assertThat(equal1).isEqualTo(equal2); assertThat(equal2).isEqualTo(equal1); assertThat(equal1.hashCode()).isEqualTo(equal2.hashCode()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/JUnitPlatformTestSuite.java000066400000000000000000000021341455764576500317210ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.Suite; /** * Test suite for the JUnit Platform. * *

Logging Configuration

* *

In order for our log4j2 configuration to be used in an IDE, you must * set the following system property before running any tests — for * example, in Run Configurations in Eclipse. * *

 * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
 * 
* * @since 1.0 */ @Suite @SelectPackages("org.junit.platform") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") class JUnitPlatformTestSuite { } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java000066400000000000000000000177531455764576500317400ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; /** * Test cases for stacktrace pruning. * *

Note: the package {@code org.junit.platform} this class resides in is * chosen on purpose. If it was in {@code org.junit.platform.launcher} * stack traces would be fully pruned. * * @since 5.10 */ class StackTracePruningTests { @Test void shouldPruneStackTraceByDefault() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceDoesNotContain(stackTrace, "jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:"); } @Test void shouldPruneStackTraceWhenEnabled() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceDoesNotContain(stackTrace, "jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:"); } @Test void shouldNotPruneStackTraceWhenDisabled() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "false") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceMatch(stackTrace, """ \\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+ >>>> \\Qorg.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:\\E.+ >>>> """); } @Test void shouldAlwaysKeepJupiterAssertionStackTraceElement() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceMatch(stackTrace, """ >>>> \\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+ >>>> """); } @Test void shouldAlwaysKeepJupiterAssumptionStackTraceElement() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssumption")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceMatch(stackTrace, """ >>>> \\Qorg.junit.jupiter.api.Assumptions.assumeTrue(Assumptions.java:\\E.+ >>>> """); } @Test void shouldKeepEverythingAfterTestCall() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "failingAssertion")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceMatch(stackTrace, """ \\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+ \\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+ \\Qorg.junit.platform.StackTracePruningTests$FailingTestTestCase.failingAssertion(StackTracePruningTests.java:\\E.+ >>>> """); } @ParameterizedTest @ValueSource(strings = { "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase", "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase", "org.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase$NestedTestCase$NestedNestedTestCase" }) void shouldKeepEverythingAfterLifecycleMethodCall(Class methodClass) { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(methodClass, "test")) // .execute(); List stackTrace = extractStackTrace(results); assertStackTraceMatch(stackTrace, """ \\Qorg.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:\\E.+ \\Qorg.junit.jupiter.api.Assertions.fail(Assertions.java:\\E.+ \\Qorg.junit.platform.StackTracePruningTests$FailingBeforeEachTestCase.setUp(StackTracePruningTests.java:\\E.+ >>>> """); } @Test void shouldPruneStackTracesOfSuppressedExceptions() { EngineExecutionResults results = EngineTestKit.engine("junit-jupiter") // .configurationParameter("junit.platform.stacktrace.pruning.enabled", "true") // .selectors(selectMethod(FailingTestTestCase.class, "multipleFailingAssertions")) // .execute(); Throwable throwable = getThrowable(results); for (Throwable suppressed : throwable.getSuppressed()) { List stackTrace = Arrays.asList(suppressed.getStackTrace()); assertStackTraceDoesNotContain(stackTrace, "jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:"); } } private static List extractStackTrace(EngineExecutionResults results) { return Arrays.asList(getThrowable(results).getStackTrace()); } private static Throwable getThrowable(EngineExecutionResults results) { var failedTestEvent = results.testEvents().failed().list().get(0); var testResult = failedTestEvent.getRequiredPayload(TestExecutionResult.class); return testResult.getThrowable().orElseThrow(); } private static void assertStackTraceMatch(List stackTrace, String expectedLines) { List stackStraceAsLines = stackTrace.stream() // .map(StackTraceElement::toString) // .collect(Collectors.toList()); assertLinesMatch(expectedLines.lines().toList(), stackStraceAsLines); } private static void assertStackTraceDoesNotContain(List stackTrace, String element) { String stackStraceAsString = stackTrace.stream() // .map(StackTraceElement::toString) // .collect(Collectors.joining()); assertThat(stackStraceAsString).doesNotContain(element); } // ------------------------------------------------------------------- static class FailingTestTestCase { @Test void failingAssertion() { Assertions.fail(); } @Test void multipleFailingAssertions() { Assertions.assertAll(Assertions::fail, Assertions::fail); } @Test void failingAssumption() { Assumptions.assumeTrue(() -> { throw new RuntimeException(); }); } } static class FailingBeforeEachTestCase { @BeforeEach void setUp() { Assertions.fail(); } @Test void test() { } @Nested class NestedTestCase { @Test void test() { } @Nested class NestedNestedTestCase { @Test void test() { } } } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/TestEngineTests.java000066400000000000000000000033661455764576500304110ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; /** * Test cases for default implementations of {@link org.junit.platform.engine.TestEngine}. * *

Note: the package {@code org.junit.platform} this class resides in is * chosen on purpose. If it was in {@code org.junit.platform.engine} the default * implementation will pick up values defined by the real Jupiter test engine. * * @since 1.1 */ class TestEngineTests { @Test void defaults() { TestEngine engine = new DefaultEngine(); assertEquals(Optional.empty(), engine.getGroupId()); assertEquals(Optional.empty(), engine.getArtifactId()); assertEquals(Optional.of("DEVELOPMENT"), engine.getVersion()); } private static class DefaultEngine implements TestEngine { @Override public String getId() { return getClass().getSimpleName(); } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { throw new UnsupportedOperationException("discover"); } @Override public void execute(ExecutionRequest request) { throw new UnsupportedOperationException("execute"); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/000077500000000000000000000000001455764576500261215ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/annotation/000077500000000000000000000000001455764576500302735ustar00rootroot00000000000000TestableAnnotationTests.java000066400000000000000000000017331455764576500357040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/annotation/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.annotation; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; /** * Integration tests that indirectly verify that the {@link Testable @Testable} * annotation may be declared on any element type. * * @since 1.7 */ class TestableAnnotationTests { @Test void testMethod() { assertNotNull(new TestableEverywhere().toString()); } @Testable static class TestableEverywhere { @Testable final int field = 0; @Testable TestableEverywhere() { } @Testable void test(@Testable int parameter) { @Testable @SuppressWarnings("unused") var var = "var"; } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/function/000077500000000000000000000000001455764576500277465ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java000066400000000000000000000100421455764576500324070ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.function; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; public class TryTests { @Test void successfulTriesCanBeTransformed() throws Exception { var success = Try.success("foo"); assertThat(success.get()).isEqualTo("foo"); assertThat(success.getOrThrow(RuntimeException::new)).isEqualTo("foo"); assertThat(success.toOptional()).contains("foo"); assertThat(success.andThen(v -> { assertThat(v).isEqualTo("foo"); return Try.success("bar"); }).get()).isEqualTo("bar"); assertThat(success.andThenTry(v -> { assertThat(v).isEqualTo("foo"); return "bar"; }).get()).isEqualTo("bar"); assertThat(success.orElse(() -> fail("should not be called"))).isSameAs(success); assertThat(success.orElseTry(() -> fail("should not be called"))).isSameAs(success); var value = new AtomicReference(); assertThat(success.ifSuccess(value::set)).isSameAs(success); assertThat(value.get()).isEqualTo("foo"); assertThat(success.ifFailure(cause -> fail("should not be called"))).isSameAs(success); } @Test void failedTriesCanBeTransformed() throws Exception { var cause = new JUnitException("foo"); var failure = Try.failure(cause); assertThat(assertThrows(JUnitException.class, failure::get)).isSameAs(cause); assertThat(assertThrows(RuntimeException.class, () -> failure.getOrThrow(RuntimeException::new))).isInstanceOf( RuntimeException.class).hasCause(cause); assertThat(failure.toOptional()).isEmpty(); assertThat(failure.andThen(v -> fail("should not be called"))).isSameAs(failure); assertThat(failure.andThenTry(v -> fail("should not be called"))).isSameAs(failure); assertThat(failure.orElse(() -> Try.success("bar")).get()).isEqualTo("bar"); assertThat(failure.orElseTry(() -> "bar").get()).isEqualTo("bar"); assertThat(failure.ifSuccess(v -> fail("should not be called"))).isSameAs(failure); var exception = new AtomicReference(); assertThat(failure.ifFailure(exception::set)).isSameAs(failure); assertThat(exception.get()).isSameAs(cause); } @Test void successfulTriesCanStoreNull() throws Exception { var success = Try.success(null); assertThat(success.get()).isNull(); assertThat(success.getOrThrow(RuntimeException::new)).isNull(); assertThat(success.toOptional()).isEmpty(); } @Test void triesWithSameContentAreEqual() { var cause = new Exception(); Callable failingCallable = () -> { throw cause; }; var success = Try.call(() -> "foo"); assertThat(success).isEqualTo(success).hasSameHashCodeAs(success); assertThat(success).isEqualTo(Try.success("foo")); assertThat(success).isNotEqualTo(Try.failure(cause)); var failure = Try.call(failingCallable); assertThat(failure).isEqualTo(failure).hasSameHashCodeAs(failure); assertThat(failure).isNotEqualTo(Try.success("foo")); assertThat(failure).isEqualTo(Try.failure(cause)); } @Test void methodPreconditionsAreChecked() { assertThrows(JUnitException.class, () -> Try.call(null)); var success = Try.success("foo"); assertThrows(JUnitException.class, () -> success.andThen(null)); assertThrows(JUnitException.class, () -> success.andThenTry(null)); assertThrows(JUnitException.class, () -> success.ifSuccess(null)); var failure = Try.failure(new Exception()); assertThrows(JUnitException.class, () -> failure.orElse(null)); assertThrows(JUnitException.class, () -> failure.orElseTry(null)); assertThrows(JUnitException.class, () -> failure.ifFailure(null)); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/000077500000000000000000000000001455764576500276355ustar00rootroot00000000000000AnnotationSupportTests.java000066400000000000000000000323261455764576500351610ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.commons.support.PreconditionAssertions.assertPreconditionViolationException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Optional; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 1.0 */ class AnnotationSupportTests { @Test void isAnnotatedPreconditions() { var optional = Optional.of(Probe.class); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.isAnnotated(optional, null)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.isAnnotated(Probe.class, null)); } @Test void isAnnotatedDelegates() { var element = Probe.class; var optional = Optional.of(element); assertEquals(AnnotationUtils.isAnnotated(optional, Tag.class), AnnotationSupport.isAnnotated(optional, Tag.class)); assertEquals(AnnotationUtils.isAnnotated(optional, Override.class), AnnotationSupport.isAnnotated(optional, Override.class)); assertEquals(AnnotationUtils.isAnnotated(element, Tag.class), AnnotationSupport.isAnnotated(element, Tag.class)); assertEquals(AnnotationUtils.isAnnotated(element, Override.class), AnnotationSupport.isAnnotated(element, Override.class)); } @Test void findAnnotationOnElementPreconditions() { var optional = Optional.of(Probe.class); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotation(optional, null)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotation(Probe.class, null)); } @Test void findAnnotationOnElementDelegates() { var element = Probe.class; var optional = Optional.of(element); assertEquals(AnnotationUtils.findAnnotation(optional, Tag.class), AnnotationSupport.findAnnotation(optional, Tag.class)); assertEquals(AnnotationUtils.findAnnotation(optional, Override.class), AnnotationSupport.findAnnotation(optional, Override.class)); assertEquals(AnnotationUtils.findAnnotation(element, Tag.class), AnnotationSupport.findAnnotation(element, Tag.class)); assertEquals(AnnotationUtils.findAnnotation(element, Override.class), AnnotationSupport.findAnnotation(element, Override.class)); } @Test void findAnnotationOnClassPreconditions() { assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotation(Probe.class, null, SearchOption.INCLUDE_ENCLOSING_CLASSES)); assertPreconditionViolationException("SearchOption", () -> AnnotationSupport.findAnnotation(Probe.class, Override.class, null)); } @Test void findAnnotationOnClassDelegates() { Class clazz = Probe.class; assertEquals(AnnotationUtils.findAnnotation(clazz, Tag.class, false), AnnotationSupport.findAnnotation(clazz, Tag.class, SearchOption.DEFAULT)); assertEquals(AnnotationUtils.findAnnotation(clazz, Tag.class, true), AnnotationSupport.findAnnotation(clazz, Tag.class, SearchOption.INCLUDE_ENCLOSING_CLASSES)); assertEquals(AnnotationUtils.findAnnotation(clazz, Override.class, false), AnnotationSupport.findAnnotation(clazz, Override.class, SearchOption.DEFAULT)); assertEquals(AnnotationUtils.findAnnotation(clazz, Override.class, true), AnnotationSupport.findAnnotation(clazz, Override.class, SearchOption.INCLUDE_ENCLOSING_CLASSES)); clazz = Probe.InnerClass.class; assertEquals(AnnotationUtils.findAnnotation(clazz, Tag.class, false), AnnotationSupport.findAnnotation(clazz, Tag.class, SearchOption.DEFAULT)); assertEquals(AnnotationUtils.findAnnotation(clazz, Tag.class, true), AnnotationSupport.findAnnotation(clazz, Tag.class, SearchOption.INCLUDE_ENCLOSING_CLASSES)); assertEquals(AnnotationUtils.findAnnotation(clazz, Override.class, false), AnnotationSupport.findAnnotation(clazz, Override.class, SearchOption.DEFAULT)); assertEquals(AnnotationUtils.findAnnotation(clazz, Override.class, true), AnnotationSupport.findAnnotation(clazz, Override.class, SearchOption.INCLUDE_ENCLOSING_CLASSES)); } @Test void findPublicAnnotatedFieldsPreconditions() { assertPreconditionViolationException("Class", () -> AnnotationSupport.findPublicAnnotatedFields(null, String.class, FieldMarker.class)); assertPreconditionViolationException("fieldType", () -> AnnotationSupport.findPublicAnnotatedFields(Probe.class, null, FieldMarker.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findPublicAnnotatedFields(Probe.class, String.class, null)); } @Test void findPublicAnnotatedFieldsDelegates() { assertEquals(AnnotationUtils.findPublicAnnotatedFields(Probe.class, String.class, FieldMarker.class), AnnotationSupport.findPublicAnnotatedFields(Probe.class, String.class, FieldMarker.class)); assertEquals(AnnotationUtils.findPublicAnnotatedFields(Probe.class, Throwable.class, Override.class), AnnotationSupport.findPublicAnnotatedFields(Probe.class, Throwable.class, Override.class)); } @Test void findAnnotatedMethodsPreconditions() { assertPreconditionViolationException("Class", () -> AnnotationSupport.findAnnotatedMethods(null, Tag.class, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedMethods(Probe.class, null, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("HierarchyTraversalMode", () -> AnnotationSupport.findAnnotatedMethods(Probe.class, Tag.class, null)); } @Test void findAnnotatedMethodsDelegates() { assertEquals( AnnotationUtils.findAnnotatedMethods(Probe.class, Tag.class, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), AnnotationSupport.findAnnotatedMethods(Probe.class, Tag.class, HierarchyTraversalMode.TOP_DOWN)); assertEquals( AnnotationUtils.findAnnotatedMethods(Probe.class, Tag.class, ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP), AnnotationSupport.findAnnotatedMethods(Probe.class, Tag.class, HierarchyTraversalMode.BOTTOM_UP)); assertEquals( AnnotationUtils.findAnnotatedMethods(Probe.class, Override.class, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), AnnotationSupport.findAnnotatedMethods(Probe.class, Override.class, HierarchyTraversalMode.TOP_DOWN)); assertEquals( AnnotationUtils.findAnnotatedMethods(Probe.class, Override.class, ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP), AnnotationSupport.findAnnotatedMethods(Probe.class, Override.class, HierarchyTraversalMode.BOTTOM_UP)); } @Test void findRepeatableAnnotationsDelegates() throws Throwable { var bMethod = Probe.class.getDeclaredMethod("bMethod"); assertEquals(AnnotationUtils.findRepeatableAnnotations(bMethod, Tag.class), AnnotationSupport.findRepeatableAnnotations(bMethod, Tag.class)); Object expected = assertThrows(PreconditionViolationException.class, () -> AnnotationUtils.findRepeatableAnnotations(bMethod, Override.class)); Object actual = assertThrows(PreconditionViolationException.class, () -> AnnotationSupport.findRepeatableAnnotations(bMethod, Override.class)); assertSame(expected.getClass(), actual.getClass(), "expected same exception class"); assertEquals(expected.toString(), actual.toString(), "expected equal exception toString representation"); } @Test void findRepeatableAnnotationsPreconditions() { assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findRepeatableAnnotations(Probe.class, null)); } @Test void findAnnotatedFieldsDelegates() { assertEquals(AnnotationUtils.findAnnotatedFields(Probe.class, FieldMarker.class, f -> true), AnnotationSupport.findAnnotatedFields(Probe.class, FieldMarker.class)); assertEquals(AnnotationUtils.findAnnotatedFields(Probe.class, Override.class, f -> true), AnnotationSupport.findAnnotatedFields(Probe.class, Override.class)); assertEquals( AnnotationUtils.findAnnotatedFields(Probe.class, FieldMarker.class, f -> true, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), AnnotationSupport.findAnnotatedFields(Probe.class, FieldMarker.class, f -> true, HierarchyTraversalMode.TOP_DOWN)); assertEquals( AnnotationUtils.findAnnotatedFields(Probe.class, Override.class, f -> true, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), AnnotationSupport.findAnnotatedFields(Probe.class, Override.class, f -> true, HierarchyTraversalMode.TOP_DOWN)); } @Test void findAnnotatedFieldsPreconditions() { assertPreconditionViolationException("Class", () -> AnnotationSupport.findAnnotatedFields(null, FieldMarker.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFields(Probe.class, null)); assertPreconditionViolationException("Class", () -> AnnotationSupport.findAnnotatedFields(null, Override.class, f -> true, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFields(Probe.class, null, f -> true, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("HierarchyTraversalMode", () -> AnnotationSupport.findAnnotatedFields(Probe.class, Override.class, f -> true, null)); } @Test void findAnnotatedFieldValuesForNonStaticFields() { var instance = new Fields(); assertThat(AnnotationSupport.findAnnotatedFieldValues(instance, Tag.class)).isEmpty(); assertThat(AnnotationSupport.findAnnotatedFieldValues(instance, FieldMarker.class))// .containsExactlyInAnyOrder("i1", "i2"); } @Test void findAnnotatedFieldValuesForStaticFields() { assertThat(AnnotationSupport.findAnnotatedFieldValues(Fields.class, Tag.class)).isEmpty(); assertThat(AnnotationSupport.findAnnotatedFieldValues(Fields.class, FieldMarker.class))// .containsExactlyInAnyOrder("s1", "s2"); } @Test void findAnnotatedFieldValuesForNonStaticFieldsByType() { var instance = new Fields(); assertThat(AnnotationSupport.findAnnotatedFieldValues(instance, FieldMarker.class, Number.class)).isEmpty(); assertThat(AnnotationSupport.findAnnotatedFieldValues(instance, FieldMarker.class, String.class))// .containsExactlyInAnyOrder("i1", "i2"); } @Test void findAnnotatedFieldValuesForStaticFieldsByType() { assertThat(AnnotationSupport.findAnnotatedFieldValues(Fields.class, FieldMarker.class, Number.class)).isEmpty(); assertThat(AnnotationSupport.findAnnotatedFieldValues(Fields.class, FieldMarker.class, String.class))// .containsExactlyInAnyOrder("s1", "s2"); } @Test void findAnnotatedFieldValuesPreconditions() { assertPreconditionViolationException("instance", () -> AnnotationSupport.findAnnotatedFieldValues((Object) null, FieldMarker.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFieldValues(this, null)); assertPreconditionViolationException("Class", () -> AnnotationSupport.findAnnotatedFieldValues(null, FieldMarker.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFieldValues(Probe.class, null)); assertPreconditionViolationException("instance", () -> AnnotationSupport.findAnnotatedFieldValues((Object) null, FieldMarker.class, Number.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFieldValues(this, null, Number.class)); assertPreconditionViolationException("fieldType", () -> AnnotationSupport.findAnnotatedFieldValues(this, FieldMarker.class, null)); assertPreconditionViolationException("Class", () -> AnnotationSupport.findAnnotatedFieldValues(null, FieldMarker.class, Number.class)); assertPreconditionViolationException("annotationType", () -> AnnotationSupport.findAnnotatedFieldValues(Probe.class, null, Number.class)); assertPreconditionViolationException("fieldType", () -> AnnotationSupport.findAnnotatedFieldValues(Probe.class, FieldMarker.class, null)); } // ------------------------------------------------------------------------- @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldMarker { } @Tag("class-tag") static class Probe { @FieldMarker public static String publicAnnotatedStaticField = "static"; @FieldMarker public String publicAnnotatedInstanceField = "instance"; @Tag("method-tag") void aMethod() { } @Tag("method-tag-1") @Tag("method-tag-2") void bMethod() { } class InnerClass { } } static class Fields { @FieldMarker static String staticField1 = "s1"; @FieldMarker static String staticField2 = "s2"; @FieldMarker String instanceField1 = "i1"; @FieldMarker String instanceField2 = "i2"; } } ClassSupportTests.java000066400000000000000000000026171455764576500341140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.commons.support.PreconditionAssertions.assertPreconditionViolationException; import java.util.List; import java.util.function.Function; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ClassUtils; /** * @since 1.1 */ class ClassSupportTests { @Test void nullSafeToStringPreconditions() { Function, ? extends String> mapper = null; assertPreconditionViolationException("Mapping function", () -> ClassSupport.nullSafeToString(mapper, String.class, List.class)); } @Test void nullSafeToStringDelegates() { assertEquals(ClassUtils.nullSafeToString(String.class, List.class), ClassSupport.nullSafeToString(String.class, List.class)); Function, String> classToStringMapper = aClass -> aClass.getSimpleName() + "-Test"; assertEquals(ClassUtils.nullSafeToString(classToStringMapper, String.class, List.class), ClassSupport.nullSafeToString(classToStringMapper, String.class, List.class)); } } ModifierSupportTests.java000066400000000000000000000156701455764576500346100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.commons.support.PreconditionAssertions.assertPreconditionViolationException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link ModifierSupport}. * * @since 1.4 */ class ModifierSupportTests { @Test void isPublicPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isPublic((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isPublic((Member) null)); } @Classes void isPublicDelegates(Class clazz) { assertEquals(ReflectionUtils.isPublic(clazz), ModifierSupport.isPublic(clazz)); } @Methods void isPublicDelegates(Method method) { assertEquals(ReflectionUtils.isPublic(method), ModifierSupport.isPublic(method)); } @Test void isPrivatePreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isPrivate((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isPrivate((Member) null)); } @Classes void isPrivateDelegates(Class clazz) { assertEquals(ReflectionUtils.isPrivate(clazz), ModifierSupport.isPrivate(clazz)); } @Methods void isPrivateDelegates(Method method) { assertEquals(ReflectionUtils.isPrivate(method), ModifierSupport.isPrivate(method)); } @Test void isNotPrivatePreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotPrivate((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isNotPrivate((Member) null)); } @Classes void isNotPrivateDelegates(Class clazz) { assertEquals(ReflectionUtils.isNotPrivate(clazz), ModifierSupport.isNotPrivate(clazz)); } @Methods void isNotPrivateDelegates(Method method) { assertEquals(ReflectionUtils.isNotPrivate(method), ModifierSupport.isNotPrivate(method)); } @Test void isAbstractPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isAbstract((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isAbstract((Member) null)); } @Classes void isAbstractDelegates(Class clazz) { assertEquals(ReflectionUtils.isAbstract(clazz), ModifierSupport.isAbstract(clazz)); } @Methods void isAbstractDelegates(Method method) { assertEquals(ReflectionUtils.isAbstract(method), ModifierSupport.isAbstract(method)); } @Test void isStaticPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isStatic((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isStatic((Member) null)); } @Classes void isStaticDelegates(Class clazz) { assertEquals(ReflectionUtils.isStatic(clazz), ModifierSupport.isStatic(clazz)); } @Methods void isStaticDelegates(Method method) { assertEquals(ReflectionUtils.isStatic(method), ModifierSupport.isStatic(method)); } @Test void isNotStaticPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotStatic((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isNotStatic((Member) null)); } @Classes void isNotStaticDelegates(Class clazz) { assertEquals(ReflectionUtils.isNotStatic(clazz), ModifierSupport.isNotStatic(clazz)); } @Methods void isNotStaticDelegates(Method method) { assertEquals(ReflectionUtils.isNotStatic(method), ModifierSupport.isNotStatic(method)); } @Test void isFinalPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isFinal((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isFinal((Member) null)); } @Classes void isFinalDelegates(Class clazz) { assertEquals(ReflectionUtils.isFinal(clazz), ModifierSupport.isFinal(clazz)); } @Methods void isFinalDelegates(Method method) { assertEquals(ReflectionUtils.isFinal(method), ModifierSupport.isFinal(method)); } @Test void isNotFinalPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotFinal((Class) null)); assertPreconditionViolationException("Member", () -> ModifierSupport.isNotFinal((Member) null)); } @Classes void isNotFinalDelegates(Class clazz) { assertEquals(ReflectionUtils.isNotFinal(clazz), ModifierSupport.isNotFinal(clazz)); } @Methods void isNotFinalDelegates(Method method) { assertEquals(ReflectionUtils.isNotFinal(method), ModifierSupport.isNotFinal(method)); } // ------------------------------------------------------------------------- // Intentionally non-static public class PublicClass { public void publicMethod() { } } private class PrivateClass { @SuppressWarnings("unused") private void privateMethod() { } } protected class ProtectedClass { @SuppressWarnings("unused") protected void protectedMethod() { } } class PackageVisibleClass { @SuppressWarnings("unused") void packageVisibleMethod() { } } abstract static class AbstractClass { abstract void abstractMethod(); } static class StaticClass { static void staticMethod() { } } final class FinalClass { final void finalMethod() { } } // ------------------------------------------------------------------------- @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest @ValueSource(classes = { PublicClass.class, PrivateClass.class, ProtectedClass.class, PackageVisibleClass.class, AbstractClass.class, StaticClass.class, FinalClass.class }) @interface Classes { } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest @MethodSource("methods") @interface Methods { } static Stream methods() throws Exception { // @formatter:off return Stream.of( PublicClass.class.getMethod("publicMethod"), PrivateClass.class.getDeclaredMethod("privateMethod"), ProtectedClass.class.getDeclaredMethod("protectedMethod"), PackageVisibleClass.class.getDeclaredMethod("packageVisibleMethod"), AbstractClass.class.getDeclaredMethod("abstractMethod"), StaticClass.class.getDeclaredMethod("staticMethod"), FinalClass.class.getDeclaredMethod("finalMethod") ); // @formatter:on } } PreconditionAssertions.java000066400000000000000000000022061455764576500351310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.PreconditionViolationException; /** * @since 1.4 */ class PreconditionAssertions { static void assertPreconditionViolationException(String name, Executable executable) { var exception = assertThrows(PreconditionViolationException.class, executable); assertEquals(name + " must not be null", exception.getMessage()); } static void assertPreconditionViolationExceptionForString(String name, Executable executable) { var exception = assertThrows(PreconditionViolationException.class, executable); assertEquals(name + " must not be null or blank", exception.getMessage()); } } ReflectionSupportTests.java000066400000000000000000000335221455764576500351400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.support; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.commons.support.PreconditionAssertions.assertPreconditionViolationException; import static org.junit.platform.commons.support.PreconditionAssertions.assertPreconditionViolationExceptionForString; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; /** * @since 1.0 */ class ReflectionSupportTests { private static final Predicate> allTypes = type -> true; private static final Predicate allNames = name -> true; private static final Predicate allMethods = name -> true; private static final Predicate allFields = name -> true; static final String staticField = "static"; final String instanceField = "instance"; @Test @SuppressWarnings("deprecation") void loadClassDelegates() { assertEquals(ReflectionUtils.loadClass("-"), ReflectionSupport.loadClass("-")); assertEquals(ReflectionUtils.loadClass("A"), ReflectionSupport.loadClass("A")); assertEquals(ReflectionUtils.loadClass("java.nio.Bits"), ReflectionSupport.loadClass("java.nio.Bits")); } @Test @SuppressWarnings("deprecation") void loadClassPreconditions() { assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.loadClass(null)); assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.loadClass("")); } @Test void tryToLoadClassDelegates() { assertEquals(ReflectionUtils.tryToLoadClass("-").toOptional(), ReflectionSupport.tryToLoadClass("-").toOptional()); assertEquals(ReflectionUtils.tryToLoadClass("A").toOptional(), ReflectionSupport.tryToLoadClass("A").toOptional()); assertEquals(ReflectionUtils.tryToLoadClass("java.nio.Bits"), ReflectionSupport.tryToLoadClass("java.nio.Bits")); } @Test void tryToLoadClassPreconditions() { assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.tryToLoadClass(null)); assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.tryToLoadClass("")); } /** * @since 1.10 */ @Test void tryToLoadClassWithExplicitClassLoaderDelegates() { ClassLoader classLoader = getClass().getClassLoader(); assertEquals(ReflectionUtils.tryToLoadClass("-", classLoader).toOptional(), ReflectionSupport.tryToLoadClass("-", classLoader).toOptional()); assertEquals(ReflectionUtils.tryToLoadClass("A", classLoader).toOptional(), ReflectionSupport.tryToLoadClass("A", classLoader).toOptional()); assertEquals(ReflectionUtils.tryToLoadClass("java.nio.Bits", classLoader), ReflectionSupport.tryToLoadClass("java.nio.Bits", classLoader)); } /** * @since 1.10 */ @Test void tryToLoadClassWithExplicitClassLoaderPreconditions() { ClassLoader cl = getClass().getClassLoader(); assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.tryToLoadClass(null, cl)); assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.tryToLoadClass("", cl)); assertPreconditionViolationException("ClassLoader", () -> ReflectionSupport.tryToLoadClass("int", null)); } @TestFactory List findAllClassesInClasspathRootDelegates() throws Throwable { List tests = new ArrayList<>(); List paths = new ArrayList<>(); paths.add(Path.of(".").toRealPath()); paths.addAll(ReflectionUtils.getAllClasspathRootDirectories()); for (var path : paths) { var root = path.toUri(); var displayName = root.getPath(); if (displayName.length() > 42) { displayName = "..." + displayName.substring(displayName.length() - 42); } tests.add(DynamicTest.dynamicTest(displayName, () -> assertEquals(ReflectionUtils.findAllClassesInClasspathRoot(root, allTypes, allNames), ReflectionSupport.findAllClassesInClasspathRoot(root, allTypes, allNames)))); } return tests; } @Test void findAllClassesInClasspathRootPreconditions() { var path = Path.of(".").toUri(); assertPreconditionViolationException("root", () -> ReflectionSupport.findAllClassesInClasspathRoot(null, allTypes, allNames)); assertPreconditionViolationException("class predicate", () -> ReflectionSupport.findAllClassesInClasspathRoot(path, null, allNames)); assertPreconditionViolationException("name predicate", () -> ReflectionSupport.findAllClassesInClasspathRoot(path, allTypes, null)); } @Test void findAllClassesInPackageDelegates() { assertNotEquals(0, ReflectionSupport.findAllClassesInPackage("org.junit", allTypes, allNames).size()); assertEquals(ReflectionUtils.findAllClassesInPackage("org.junit", allTypes, allNames), ReflectionSupport.findAllClassesInPackage("org.junit", allTypes, allNames)); } @Test void findAllClassesInPackagePreconditions() { assertPreconditionViolationExceptionForString("basePackageName", () -> ReflectionSupport.findAllClassesInPackage(null, allTypes, allNames)); assertPreconditionViolationException("class predicate", () -> ReflectionSupport.findAllClassesInPackage("org.junit", null, allNames)); assertPreconditionViolationException("name predicate", () -> ReflectionSupport.findAllClassesInPackage("org.junit", allTypes, null)); } @Test void findAllClassesInModuleDelegates() { assertEquals(ReflectionUtils.findAllClassesInModule("org.junit.platform.commons", allTypes, allNames), ReflectionSupport.findAllClassesInModule("org.junit.platform.commons", allTypes, allNames)); } @Test void findAllClassesInModulePreconditions() { var exception = assertThrows(PreconditionViolationException.class, () -> ReflectionSupport.findAllClassesInModule(null, allTypes, allNames)); assertEquals("Module name must not be null or empty", exception.getMessage()); assertPreconditionViolationException("class predicate", () -> ReflectionSupport.findAllClassesInModule("org.junit.platform.commons", null, allNames)); assertPreconditionViolationException("name predicate", () -> ReflectionSupport.findAllClassesInModule("org.junit.platform.commons", allTypes, null)); } @Test void newInstanceDelegates() { assertEquals(ReflectionUtils.newInstance(String.class, "foo"), ReflectionSupport.newInstance(String.class, "foo")); } @Test void newInstancePreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.newInstance(null)); assertPreconditionViolationException("Argument array", () -> ReflectionSupport.newInstance(String.class, (Object[]) null)); assertPreconditionViolationException("Individual arguments", () -> ReflectionSupport.newInstance(String.class, new Object[] { null })); } @Test void invokeMethodDelegates() throws Exception { var method = Boolean.class.getMethod("valueOf", String.class); assertEquals(ReflectionUtils.invokeMethod(method, null, "true"), ReflectionSupport.invokeMethod(method, null, "true")); } @Test void invokeMethodPreconditions() throws Exception { assertPreconditionViolationException("Method", () -> ReflectionSupport.invokeMethod(null, null, "true")); var method = Boolean.class.getMethod("toString"); var exception = assertThrows(PreconditionViolationException.class, () -> ReflectionSupport.invokeMethod(method, null)); assertEquals("Cannot invoke non-static method [" + method.toGenericString() + "] on a null target.", exception.getMessage()); } @Test void findFieldsDelegates() { assertEquals( ReflectionUtils.findFields(ReflectionSupportTests.class, allFields, ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP), ReflectionSupport.findFields(ReflectionSupportTests.class, allFields, HierarchyTraversalMode.BOTTOM_UP)); assertEquals( ReflectionUtils.findFields(ReflectionSupportTests.class, allFields, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), ReflectionSupport.findFields(ReflectionSupportTests.class, allFields, HierarchyTraversalMode.TOP_DOWN)); } @Test void findFieldsPreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.findFields(null, allFields, HierarchyTraversalMode.BOTTOM_UP)); assertPreconditionViolationException("Class", () -> ReflectionSupport.findFields(null, allFields, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("Predicate", () -> ReflectionSupport.findFields(ReflectionSupportTests.class, null, HierarchyTraversalMode.BOTTOM_UP)); assertPreconditionViolationException("Predicate", () -> ReflectionSupport.findFields(ReflectionSupportTests.class, null, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("HierarchyTraversalMode", () -> ReflectionSupport.findFields(ReflectionSupportTests.class, allFields, null)); } @Test void tryToReadFieldValueDelegates() throws Exception { var staticField = getClass().getDeclaredField("staticField"); assertEquals(ReflectionUtils.tryToReadFieldValue(staticField, null), ReflectionSupport.tryToReadFieldValue(staticField, null)); var instanceField = getClass().getDeclaredField("instanceField"); assertEquals(ReflectionUtils.tryToReadFieldValue(instanceField, this), ReflectionSupport.tryToReadFieldValue(instanceField, this)); } @Test void tryToReadFieldValuePreconditions() throws Exception { assertPreconditionViolationException("Field", () -> ReflectionSupport.tryToReadFieldValue(null, this)); var instanceField = getClass().getDeclaredField("instanceField"); Exception exception = assertThrows(PreconditionViolationException.class, () -> ReflectionSupport.tryToReadFieldValue(instanceField, null)); assertThat(exception)// .hasMessageStartingWith("Cannot read non-static field")// .hasMessageEndingWith("on a null instance."); } @Test void findMethodDelegates() { assertEquals(ReflectionUtils.findMethod(Boolean.class, "valueOf", String.class.getName()), ReflectionSupport.findMethod(Boolean.class, "valueOf", String.class.getName())); assertEquals(ReflectionUtils.findMethod(Boolean.class, "valueOf", String.class), ReflectionSupport.findMethod(Boolean.class, "valueOf", String.class)); } @Test void findMethodPreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.findMethod(null, "valueOf", String.class.getName())); assertPreconditionViolationExceptionForString("Method name", () -> ReflectionSupport.findMethod(Boolean.class, "", String.class.getName())); assertPreconditionViolationExceptionForString("Method name", () -> ReflectionSupport.findMethod(Boolean.class, " ", String.class.getName())); assertPreconditionViolationException("Class", () -> ReflectionSupport.findMethod(null, "valueOf", String.class)); assertPreconditionViolationExceptionForString("Method name", () -> ReflectionSupport.findMethod(Boolean.class, "", String.class)); assertPreconditionViolationExceptionForString("Method name", () -> ReflectionSupport.findMethod(Boolean.class, " ", String.class)); assertPreconditionViolationException("Parameter types array", () -> ReflectionSupport.findMethod(Boolean.class, "valueOf", (Class[]) null)); assertPreconditionViolationException("Individual parameter types", () -> ReflectionSupport.findMethod(Boolean.class, "valueOf", new Class[] { null })); } @Test void findMethodsDelegates() { assertEquals( ReflectionUtils.findMethods(ReflectionSupportTests.class, allMethods, ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP), ReflectionSupport.findMethods(ReflectionSupportTests.class, allMethods, HierarchyTraversalMode.BOTTOM_UP)); assertEquals( ReflectionUtils.findMethods(ReflectionSupportTests.class, allMethods, ReflectionUtils.HierarchyTraversalMode.TOP_DOWN), ReflectionSupport.findMethods(ReflectionSupportTests.class, allMethods, HierarchyTraversalMode.TOP_DOWN)); } @Test void findMethodsPreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.findMethods(null, allMethods, HierarchyTraversalMode.BOTTOM_UP)); assertPreconditionViolationException("Class", () -> ReflectionSupport.findMethods(null, allMethods, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("Predicate", () -> ReflectionSupport.findMethods(ReflectionSupportTests.class, null, HierarchyTraversalMode.BOTTOM_UP)); assertPreconditionViolationException("Predicate", () -> ReflectionSupport.findMethods(ReflectionSupportTests.class, null, HierarchyTraversalMode.TOP_DOWN)); assertPreconditionViolationException("HierarchyTraversalMode", () -> ReflectionSupport.findMethods(ReflectionSupportTests.class, allMethods, null)); } @Test void findNestedClassesDelegates() { assertEquals(ReflectionUtils.findNestedClasses(ClassWithNestedClasses.class, ReflectionUtils::isStatic), ReflectionSupport.findNestedClasses(ClassWithNestedClasses.class, ReflectionUtils::isStatic)); } @Test void findNestedClassesPreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.findNestedClasses(null, ReflectionUtils::isStatic)); assertPreconditionViolationException("Predicate", () -> ReflectionSupport.findNestedClasses(ClassWithNestedClasses.class, null)); } static class ClassWithNestedClasses { class Nested1 { } static class Nested2 { } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/000077500000000000000000000000001455764576500270765ustar00rootroot00000000000000AnnotationUtilsTests.java000066400000000000000000000752351455764576500340540ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotatedMethods; import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; import static org.junit.platform.commons.util.AnnotationUtils.findPublicAnnotatedFields; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.pkg1.ClassLevelDir; import org.junit.platform.commons.util.pkg1.InstanceLevelDir; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateBeforeMethod; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateTempDirField; import org.junit.platform.commons.util.pkg1.subpkg.SubclassWithNonStaticPackagePrivateBeforeMethod; import org.junit.platform.commons.util.pkg1.subpkg.SubclassWithNonStaticPackagePrivateTempDirField; /** * Unit tests for {@link AnnotationUtils}. * * @since 1.0 */ class AnnotationUtilsTests { private static final Predicate isStringField = field -> field.getType() == String.class; @Test void findAnnotationForNullOptional() { assertThat(findAnnotation((Optional) null, Annotation1.class)).isEmpty(); } @Test void findAnnotationForEmptyOptional() { assertThat(findAnnotation(Optional.empty(), Annotation1.class)).isEmpty(); } @Test void findAnnotationForNullAnnotatedElement() { assertThat(findAnnotation((AnnotatedElement) null, Annotation1.class)).isEmpty(); } @Test void findAnnotationOnClassWithoutAnnotation() { assertThat(findAnnotation(Annotation1Class.class, Annotation2.class)).isNotPresent(); } @Test void findAnnotationIndirectlyPresentOnOptionalClass() { Optional> optional = Optional.of(SubInheritedAnnotationClass.class); assertThat(findAnnotation(optional, InheritedAnnotation.class)).isPresent(); } @Test void findAnnotationIndirectlyPresentOnClass() { assertThat(findAnnotation(SubInheritedAnnotationClass.class, InheritedAnnotation.class)).isPresent(); } /** * Test for https://github.com/junit-team/junit5/issues/1133 */ @Test void findInheritedAnnotationMetaPresentOnNonInheritedComposedAnnotationPresentOnSuperclass() { assertThat(findAnnotation(SubNonInheritedCompositionOfInheritedAnnotationClass.class, InheritedAnnotation.class)).isPresent(); } @Test void findAnnotationDirectlyPresentOnClass() { assertThat(findAnnotation(Annotation1Class.class, Annotation1.class)).isPresent(); } @Test void findAnnotationMetaPresentOnClass() { assertThat(findAnnotation(ComposedAnnotationClass.class, Annotation1.class)).isPresent(); } /** * Note: there is no findAnnotationIndirectlyMetaPresentOnMethod * counterpart because the {@code @Inherited} annotation has no effect if * the annotation type is used to annotate anything other than a class. * * @see Inherited */ @Test void findAnnotationIndirectlyMetaPresentOnClass() { assertThat(findAnnotation(SubInheritedComposedAnnotationClass.class, Annotation1.class)).isPresent(); } @Test void findAnnotationDirectlyPresentOnImplementedInterface() { assertThat(findAnnotation(TestingTraitClass.class, Annotation1.class)).isPresent(); } @Test void findAnnotationMetaPresentOnImplementedInterface() { assertThat(findAnnotation(ComposedTestingTraitClass.class, Annotation1.class)).isPresent(); } @Test void findAnnotationDirectlyPresentOnMethod() throws Exception { var method = Annotation2Class.class.getDeclaredMethod("method"); assertThat(findAnnotation(method, Annotation1.class)).isPresent(); } @Test void findAnnotationMetaPresentOnMethod() throws Exception { var method = ComposedAnnotationClass.class.getDeclaredMethod("method"); assertThat(findAnnotation(method, Annotation1.class)).isPresent(); } @Test void findAnnotationMetaPresentOnOptionalMethod() throws Exception { var method = ComposedAnnotationClass.class.getDeclaredMethod("method"); assertThat(findAnnotation(Optional.of(method), Annotation1.class)).isPresent(); } @Test void findAnnotationDirectlyPresentOnEnclosingClass() throws Exception { Class clazz = Annotation1Class.InnerClass.class; assertThat(findAnnotation(clazz, Annotation1.class, false)).isNotPresent(); assertThat(findAnnotation(clazz, Annotation1.class, true)).isPresent(); clazz = Annotation1Class.InnerClass.InnerInnerClass.class; assertThat(findAnnotation(clazz, Annotation1.class, false)).isNotPresent(); assertThat(findAnnotation(clazz, Annotation1.class, true)).isPresent(); clazz = Annotation1Class.NestedClass.class; assertThat(findAnnotation(clazz, Annotation1.class, false)).isNotPresent(); assertThat(findAnnotation(clazz, Annotation1.class, true)).isNotPresent(); } @Test void findAnnotationMetaPresentOnEnclosingClass() throws Exception { Class clazz = ComposedAnnotationClass.InnerClass.class; assertThat(findAnnotation(clazz, Annotation1.class, false)).isNotPresent(); assertThat(findAnnotation(clazz, Annotation1.class, true)).isPresent(); clazz = ComposedAnnotationClass.InnerClass.InnerInnerClass.class; assertThat(findAnnotation(clazz, Annotation1.class, false)).isNotPresent(); assertThat(findAnnotation(clazz, Annotation1.class, true)).isPresent(); } @Test void isAnnotatedForClassWithoutAnnotation() { assertFalse(isAnnotated(Annotation1Class.class, Annotation2.class)); } @Test void isAnnotatedWhenIndirectlyPresentOnClass() { assertTrue(isAnnotated(SubInheritedAnnotationClass.class, InheritedAnnotation.class)); } @Test void isAnnotatedWhenDirectlyPresentOnClass() { assertTrue(isAnnotated(Annotation1Class.class, Annotation1.class)); } @Test void isAnnotatedWhenMetaPresentOnClass() { assertTrue(isAnnotated(ComposedAnnotationClass.class, Annotation1.class)); } @Test void isAnnotatedWhenDirectlyPresentOnMethod() throws Exception { assertTrue(isAnnotated(Annotation2Class.class.getDeclaredMethod("method"), Annotation1.class)); } @Test void isAnnotatedWhenMetaPresentOnMethod() throws Exception { assertTrue(isAnnotated(ComposedAnnotationClass.class.getDeclaredMethod("method"), Annotation1.class)); } @Test void findRepeatableAnnotationsForNotRepeatableAnnotation() { var exception = assertThrows(PreconditionViolationException.class, () -> findRepeatableAnnotations(getClass(), Inherited.class)); assertThat(exception.getMessage()).isEqualTo(Inherited.class.getName() + " must be @Repeatable"); } @Test void findRepeatableAnnotationsForNullOptionalAnnotatedElement() { assertThat(findRepeatableAnnotations((Optional) null, Tag.class)).isEmpty(); } @Test void findRepeatableAnnotationsForEmptyOptionalAnnotatedElement() { assertThat(findRepeatableAnnotations(Optional.empty(), Tag.class)).isEmpty(); } @Test void findRepeatableAnnotationsForNullAnnotatedElement() { assertThat(findRepeatableAnnotations((AnnotatedElement) null, Tag.class)).isEmpty(); } @Test void findRepeatableAnnotationsWithSingleTag() { assertTagsFound(SingleTaggedClass.class, "a"); } @Test void findRepeatableAnnotationsWithSingleComposedTag() { assertTagsFound(SingleComposedTaggedClass.class, "fast"); } @Test void findRepeatableAnnotationsWithSingleComposedTagOnImplementedInterface() { assertTagsFound(TaggedInterfaceClass.class, "fast"); } @Test void findRepeatableAnnotationsWithLocalComposedTagAndComposedTagOnImplementedInterface() { assertTagsFound(LocalTagOnTaggedInterfaceClass.class, "fast", "smoke"); } @Test void findRepeatableAnnotationsWithMultipleTags() { assertTagsFound(MultiTaggedClass.class, "a", "b", "c"); } @Test void findRepeatableAnnotationsWithMultipleComposedTags() { assertTagsFound(MultiComposedTaggedClass.class, "fast", "smoke"); assertTagsFound(FastAndSmokyTaggedClass.class, "fast", "smoke"); } @Test void findRepeatableAnnotationsWithContainer() { assertTagsFound(ContainerTaggedClass.class, "a", "b", "c", "d"); } @Test void findRepeatableAnnotationsWithComposedTagBeforeContainer() { assertTagsFound(ContainerAfterComposedTaggedClass.class, "fast", "a", "b", "c"); } private void assertTagsFound(Class clazz, String... tags) { assertEquals(List.of(tags), findRepeatableAnnotations(clazz, Tag.class).stream().map(Tag::value).collect(toList()), () -> "Tags found for class " + clazz.getName()); } @Test void findInheritedRepeatableAnnotationsWithSingleAnnotationOnSuperclass() { assertExtensionsFound(SingleExtensionClass.class, "a"); assertExtensionsFound(SubSingleExtensionClass.class, "a"); } @Test void findInheritedRepeatableAnnotationsWithMultipleAnnotationsOnSuperclass() { assertExtensionsFound(MultiExtensionClass.class, "a", "b", "c"); assertExtensionsFound(SubMultiExtensionClass.class, "a", "b", "c", "x", "y", "z"); } @Test void findInheritedRepeatableAnnotationsWithContainerAnnotationOnSuperclass() { assertExtensionsFound(ContainerExtensionClass.class, "a", "b", "c"); assertExtensionsFound(SubContainerExtensionClass.class, "a", "b", "c", "x"); } @Test void findInheritedRepeatableAnnotationsWithSingleComposedAnnotation() { assertExtensionsFound(SingleComposedExtensionClass.class, "foo"); } /** * @since 1.5 */ @Test void findInheritedRepeatableAnnotationsWithComposedAnnotationsInNestedContainer() { assertExtensionsFound(MultipleFoos1.class, "foo"); assertExtensionsFound(MultipleFoos2.class, "foo"); } @Test void findInheritedRepeatableAnnotationsWithSingleComposedAnnotationOnSuperclass() { assertExtensionsFound(SubSingleComposedExtensionClass.class, "foo"); } @Test void findInheritedRepeatableAnnotationsWithMultipleComposedAnnotations() { assertExtensionsFound(MultiComposedExtensionClass.class, "foo", "bar"); } @Test void findInheritedRepeatableAnnotationsWithMultipleComposedAnnotationsOnSuperclass() { assertExtensionsFound(SubMultiComposedExtensionClass.class, "foo", "bar"); } @Test void findInheritedRepeatableAnnotationsWithMultipleComposedAnnotationsOnSuperclassAndLocalContainerAndComposed() { assertExtensionsFound(ContainerPlusSubMultiComposedExtensionClass.class, "foo", "bar", "x", "y", "z"); } private void assertExtensionsFound(Class clazz, String... tags) { assertEquals(List.of(tags), findRepeatableAnnotations(clazz, ExtendWith.class).stream().map(ExtendWith::value).collect(toList()), () -> "Extensions found for class " + clazz.getName()); } @Test void findAnnotatedMethodsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedMethods(null, Annotation1.class, TOP_DOWN)); } @Test void findAnnotatedMethodsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedMethods(ClassWithAnnotatedMethods.class, null, TOP_DOWN)); } @Test void findAnnotatedMethodsForAnnotationThatIsNotPresent() { assertThat(findAnnotatedMethods(ClassWithAnnotatedMethods.class, Fast.class, TOP_DOWN)).isEmpty(); } @Test void findAnnotatedMethodsForAnnotationOnMethodsInClassUsingHierarchyDownMode() throws Exception { var method2 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method2"); var method3 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method3"); var methods = findAnnotatedMethods(ClassWithAnnotatedMethods.class, Annotation2.class, TOP_DOWN); assertThat(methods).containsOnly(method2, method3); } @Test void findAnnotatedMethodsForAnnotationOnMethodsInClassHierarchyUsingHierarchyUpMode() throws Exception { var method1 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method1"); var method3 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method3"); var superMethod = SuperclassWithAnnotatedMethod.class.getDeclaredMethod("superMethod"); var methods = findAnnotatedMethods(ClassWithAnnotatedMethods.class, Annotation1.class, BOTTOM_UP); assertEquals(3, methods.size()); assertThat(methods.subList(0, 2)).containsOnly(method1, method3); assertEquals(superMethod, methods.get(2)); } @Test void findAnnotatedMethodsForAnnotationUsedInClassAndSuperclassHierarchyDown() throws Exception { var method1 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method1"); var method3 = ClassWithAnnotatedMethods.class.getDeclaredMethod("method3"); var superMethod = SuperclassWithAnnotatedMethod.class.getDeclaredMethod("superMethod"); var methods = findAnnotatedMethods(ClassWithAnnotatedMethods.class, Annotation1.class, TOP_DOWN); assertEquals(3, methods.size()); assertEquals(superMethod, methods.get(0)); assertThat(methods.subList(1, 3)).containsOnly(method1, method3); } /** * @see https://github.com/junit-team/junit5/issues/3553 */ @Disabled("Until #3553 is resolved") @Test void findAnnotatedMethodsDoesNotAllowInstanceMethodToHideStaticMethod() throws Exception { final String BEFORE = "before"; Class superclass = SuperclassWithStaticPackagePrivateBeforeMethod.class; Method beforeAllMethod = superclass.getDeclaredMethod(BEFORE); Class subclass = SubclassWithNonStaticPackagePrivateBeforeMethod.class; Method beforeEachMethod = subclass.getDeclaredMethod(BEFORE); // Prerequisite var methods = findAnnotatedMethods(superclass, BeforeAll.class, TOP_DOWN); assertThat(methods).containsExactly(beforeAllMethod); // Actual use cases for this test methods = findAnnotatedMethods(subclass, BeforeAll.class, TOP_DOWN); assertThat(methods).containsExactly(beforeAllMethod); methods = findAnnotatedMethods(subclass, BeforeEach.class, TOP_DOWN); assertThat(methods).containsExactly(beforeEachMethod); } @Test void findAnnotatedMethodsForAnnotationUsedInInterface() throws Exception { var interfaceMethod = InterfaceWithAnnotatedDefaultMethod.class.getDeclaredMethod("interfaceMethod"); var methods = findAnnotatedMethods(ClassWithAnnotatedMethods.class, Annotation3.class, BOTTOM_UP); assertThat(methods).containsExactly(interfaceMethod); } // === findAnnotatedFields() =============================================== @Test void findAnnotatedFieldsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedFields(null, Annotation1.class, isStringField, TOP_DOWN)); } @Test void findAnnotatedFieldsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedFields(ClassWithAnnotatedFields.class, null, isStringField, TOP_DOWN)); } @Test void findAnnotatedFieldsForNullPredicate() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedFields(ClassWithAnnotatedFields.class, Annotation1.class, null, TOP_DOWN)); } @Test void findAnnotatedFieldsForAnnotationThatIsNotPresent() { assertThat(findAnnotatedFields(ClassWithAnnotatedFields.class, Fast.class, isStringField, TOP_DOWN)).isEmpty(); } @Test void findAnnotatedFieldsForAnnotationOnFieldsInClassUsingHierarchyDownMode() throws Exception { var field2 = ClassWithAnnotatedFields.class.getDeclaredField("field2"); var field3 = ClassWithAnnotatedFields.class.getDeclaredField("field3"); var fields = findAnnotatedFields(ClassWithAnnotatedFields.class, Annotation2.class, isStringField, TOP_DOWN); assertThat(fields).containsOnly(field2, field3); } @Test void findAnnotatedFieldsForAnnotationOnFieldsInClassHierarchyUsingHierarchyUpMode() throws Exception { var field1 = ClassWithAnnotatedFields.class.getDeclaredField("field1"); var field3 = ClassWithAnnotatedFields.class.getDeclaredField("field3"); var superField = SuperclassWithAnnotatedField.class.getDeclaredField("superField"); var fields = findAnnotatedFields(ClassWithAnnotatedFields.class, Annotation1.class, isStringField, BOTTOM_UP); assertEquals(3, fields.size()); assertThat(fields.subList(0, 2)).containsOnly(field1, field3); assertEquals(superField, fields.get(2)); } @Test void findAnnotatedFieldsForAnnotationUsedInClassAndSuperclassHierarchyDown() throws Exception { var field1 = ClassWithAnnotatedFields.class.getDeclaredField("field1"); var field3 = ClassWithAnnotatedFields.class.getDeclaredField("field3"); var superField = SuperclassWithAnnotatedField.class.getDeclaredField("superField"); var fields = findAnnotatedFields(ClassWithAnnotatedFields.class, Annotation1.class, isStringField, TOP_DOWN); assertEquals(3, fields.size()); assertEquals(superField, fields.get(0)); assertThat(fields.subList(1, 3)).containsOnly(field1, field3); } @Test void findAnnotatedFieldsForAnnotationUsedInInterface() throws Exception { var interfaceField = InterfaceWithAnnotatedField.class.getDeclaredField("interfaceField"); var fields = findAnnotatedFields(ClassWithAnnotatedFields.class, Annotation3.class, isStringField, BOTTOM_UP); assertThat(fields).containsExactly(interfaceField); } @Test void findAnnotatedFieldsForShadowedFields() throws Exception { Class clazz = ClassWithShadowedAnnotatedFields.class; var interfaceField = clazz.getDeclaredField("interfaceField"); var superField = clazz.getDeclaredField("superField"); var field1 = clazz.getDeclaredField("field1"); var field2 = clazz.getDeclaredField("field2"); var field3 = clazz.getDeclaredField("field3"); assertThat(findShadowingAnnotatedFields(Annotation1.class)).containsExactly(superField, field1, field3); assertThat(findShadowingAnnotatedFields(Annotation2.class)).containsExactly(field2, field3); assertThat(findShadowingAnnotatedFields(Annotation3.class)).containsExactly(interfaceField); } private List findShadowingAnnotatedFields(Class annotationType) { return findAnnotatedFields(ClassWithShadowedAnnotatedFields.class, annotationType, isStringField); } /** * @see https://github.com/junit-team/junit5/issues/3553 */ @Disabled("Until #3553 is resolved") @Test void findAnnotatedFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exception { final String TEMP_DIR = "tempDir"; Class superclass = SuperclassWithStaticPackagePrivateTempDirField.class; Field staticField = superclass.getDeclaredField(TEMP_DIR); Class subclass = SubclassWithNonStaticPackagePrivateTempDirField.class; Field nonStaticField = subclass.getDeclaredField(TEMP_DIR); // Prerequisite var fields = findAnnotatedFields(superclass, ClassLevelDir.class, field -> true); assertThat(fields).containsExactly(staticField); // Actual use cases for this test fields = findAnnotatedFields(subclass, ClassLevelDir.class, field -> true); assertThat(fields).containsExactly(staticField); fields = findAnnotatedFields(subclass, InstanceLevelDir.class, field -> true); assertThat(fields).containsExactly(nonStaticField); } // === findPublicAnnotatedFields() ========================================= @Test void findPublicAnnotatedFieldsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findPublicAnnotatedFields(null, String.class, Annotation1.class)); } @Test void findPublicAnnotatedFieldsForNullFieldType() { assertThrows(PreconditionViolationException.class, () -> findPublicAnnotatedFields(getClass(), null, Annotation1.class)); } @Test void findPublicAnnotatedFieldsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, () -> findPublicAnnotatedFields(getClass(), String.class, null)); } @Test void findPublicAnnotatedFieldsForPrivateField() { var fields = findPublicAnnotatedFields(getClass(), Boolean.class, Annotation1.class); assertNotNull(fields); assertEquals(0, fields.size()); } @Test void findPublicAnnotatedFieldsForDirectlyAnnotatedFieldOfWrongFieldType() { var fields = findPublicAnnotatedFields(getClass(), BigDecimal.class, Annotation1.class); assertNotNull(fields); assertEquals(0, fields.size()); } @Test void findPublicAnnotatedFieldsForDirectlyAnnotatedField() { var fields = findPublicAnnotatedFields(getClass(), String.class, Annotation1.class); assertNotNull(fields); assertIterableEquals(List.of("directlyAnnotatedField"), asNames(fields)); } @Test void findPublicAnnotatedFieldsForMetaAnnotatedField() { var fields = findPublicAnnotatedFields(getClass(), Number.class, Annotation1.class); assertNotNull(fields); assertEquals(1, fields.size()); assertIterableEquals(List.of("metaAnnotatedField"), asNames(fields)); } @Test void findPublicAnnotatedFieldsForDirectlyAnnotatedFieldInInterface() { var fields = findPublicAnnotatedFields(InterfaceWithAnnotatedFields.class, String.class, Annotation1.class); assertNotNull(fields); assertIterableEquals(List.of("foo"), asNames(fields)); } @Test void findPublicAnnotatedFieldsForDirectlyAnnotatedFieldsInClassAndInterface() { var fields = findPublicAnnotatedFields(ClassWithPublicAnnotatedFieldsFromInterface.class, String.class, Annotation1.class); assertNotNull(fields); assertThat(asNames(fields)).containsExactlyInAnyOrder("foo", "bar"); } private List asNames(List fields) { return fields.stream().map(Field::getName).collect(toList()); } // ------------------------------------------------------------------------- @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface AnnotationWithDefaultValue { String value() default "default"; } @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @interface Annotation1 { } @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @interface Annotation2 { } @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @interface Annotation3 { } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited @interface InheritedAnnotation { } @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Annotation1 @interface ComposedAnnotation { } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Annotation1 @Inherited @interface InheritedComposedAnnotation { } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @InheritedAnnotation // DO NOT make this @Inherited. @interface NonInheritedCompositionOfInheritedAnnotation { } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) // DO NOT make this @Inherited. @interface Tags { Tag[] value(); } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Tags.class) // DO NOT make this @Inherited. @interface Tag { String value(); } @Retention(RetentionPolicy.RUNTIME) @Tag("fast") @interface Fast { } @Retention(RetentionPolicy.RUNTIME) @Tag("smoke") @interface Smoke { } @Retention(RetentionPolicy.RUNTIME) @Fast @Smoke @interface FastAndSmoky { } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @interface Extensions { ExtendWith[] value(); } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(Extensions.class) @interface ExtendWith { String value(); } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @ExtendWith("foo") @Repeatable(FooExtensions.class) @interface ExtendWithFoo { String info() default ""; } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @interface FooExtensions { ExtendWithFoo[] value(); } @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) // Intentionally NOT @Inherited in order to ensure that the algorithm for // findRepeatableAnnotations() in fact lives up to the claims in the // Javadoc regarding searching for repeatable annotations with implicit // "inheritance" if the repeatable annotation is @Inherited but the // custom composed annotation is not @Inherited. // @Inherited @ExtendWith("bar") @interface ExtendWithBar { } @AnnotationWithDefaultValue static class AnnotationWithDefaultValueClass { } @Annotation1 static class Annotation1Class { class InnerClass { class InnerInnerClass { } } static class NestedClass { } } @Annotation2 static class Annotation2Class { @Annotation1 void method() { } } @InheritedAnnotation static class InheritedAnnotationClass { } static class SubInheritedAnnotationClass extends InheritedAnnotationClass { } @ComposedAnnotation static class ComposedAnnotationClass { @ComposedAnnotation void method() { } class InnerClass { class InnerInnerClass { } } } @InheritedComposedAnnotation static class InheritedComposedAnnotationClass { @InheritedComposedAnnotation void method() { } } static class SubInheritedComposedAnnotationClass extends InheritedComposedAnnotationClass { } @NonInheritedCompositionOfInheritedAnnotation static class NonInheritedCompositionOfInheritedAnnotationClass { } static class SubNonInheritedCompositionOfInheritedAnnotationClass extends NonInheritedCompositionOfInheritedAnnotationClass { } @Annotation1 interface TestingTrait { } static class TestingTraitClass implements TestingTrait { } @ComposedAnnotation interface ComposedTestingTrait { } static class ComposedTestingTraitClass implements ComposedTestingTrait { } @Tag("a") static class SingleTaggedClass { } @Fast static class SingleComposedTaggedClass { } @Tag("a") @Tag("b") @Tag("c") static class MultiTaggedClass { } @Fast @Smoke static class MultiComposedTaggedClass { } @FastAndSmoky static class FastAndSmokyTaggedClass { } @Fast interface TaggedInterface { } static class TaggedInterfaceClass implements TaggedInterface { } @Smoke static class LocalTagOnTaggedInterfaceClass implements TaggedInterface { } @Tags({ @Tag("a"), @Tag("b"), @Tag("c") }) @Tag("d") static class ContainerTaggedClass { } @Fast @Tags({ @Tag("a"), @Tag("b"), @Tag("c") }) static class ContainerAfterComposedTaggedClass { } @ExtendWith("a") static class SingleExtensionClass { } static class SubSingleExtensionClass extends SingleExtensionClass { } @ExtendWith("a") @ExtendWith("b") @ExtendWith("c") static class MultiExtensionClass { } @ExtendWith("x") @ExtendWith("y") @ExtendWith("b") // duplicates parent @ExtendWith("z") @ExtendWith("a") // duplicates parent static class SubMultiExtensionClass extends MultiExtensionClass { } @Extensions({ @ExtendWith("a"), @ExtendWith("b"), @ExtendWith("c"), @ExtendWith("a") }) static class ContainerExtensionClass { } @ExtendWith("x") static class SubContainerExtensionClass extends ContainerExtensionClass { } @ExtendWithFoo static class SingleComposedExtensionClass { } @ExtendWithFoo(info = "A") @ExtendWithFoo(info = "B") static class MultipleFoos1 { } @FooExtensions({ @ExtendWithFoo(info = "A"), @ExtendWithFoo(info = "B") }) static class MultipleFoos2 { } static class SubSingleComposedExtensionClass extends SingleComposedExtensionClass { } @ExtendWithFoo @ExtendWithBar static class MultiComposedExtensionClass { } static class SubMultiComposedExtensionClass extends MultiComposedExtensionClass { } @ExtendWith("x") @Extensions({ @ExtendWith("y"), @ExtendWith("z") }) @ExtendWithBar static class ContainerPlusSubMultiComposedExtensionClass extends MultiComposedExtensionClass { } interface InterfaceWithAnnotatedDefaultMethod { @Annotation3 default void interfaceMethod() { } } static class SuperclassWithAnnotatedMethod { @Annotation1 void superMethod() { } } static class ClassWithAnnotatedMethods extends SuperclassWithAnnotatedMethod implements InterfaceWithAnnotatedDefaultMethod { @Annotation1 void method1() { } @Annotation2 void method2() { } @Annotation1 @Annotation2 void method3() { } } // ------------------------------------------------------------------------- interface InterfaceWithAnnotatedField { @Annotation3 String interfaceField = "interface"; } static class SuperclassWithAnnotatedField { @Annotation1 String superField = "super"; } static class ClassWithAnnotatedFields extends SuperclassWithAnnotatedField implements InterfaceWithAnnotatedField { @Annotation1 protected Object field0 = "?"; @Annotation1 protected String field1 = "foo"; @Annotation2 protected String field2 = "bar"; @Annotation1 @Annotation2 protected String field3 = "baz"; } static class ClassWithShadowedAnnotatedFields extends ClassWithAnnotatedFields { @Annotation3 String interfaceField = "interface-shadow"; @Annotation1 String superField = "super-shadow"; @Annotation1 protected String field1 = "foo-shadow"; @Annotation2 protected String field2 = "bar-shadow"; @Annotation1 @Annotation2 protected String field3 = "baz-shadow"; } // ------------------------------------------------------------------------- @Annotation1 private Boolean privateDirectlyAnnotatedField; @Annotation1 public String directlyAnnotatedField; @ComposedAnnotation public Integer metaAnnotatedField; interface InterfaceWithAnnotatedFields { @Annotation1 String foo = "bar"; @Annotation1 boolean wrongType = false; } class ClassWithPublicAnnotatedFieldsFromInterface implements InterfaceWithAnnotatedFields { @Annotation1 public String bar = "baz"; @Annotation1 public boolean notAString = true; } } ClassLoaderUtilsTests.java000066400000000000000000000077241455764576500341340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.test.TestClassLoader; /** * Unit tests for {@link ClassLoaderUtils}. * * @since 1.0 */ class ClassLoaderUtilsTests { @Test void getClassLoaderPreconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> ClassLoaderUtils.getClassLoader(null))// .withMessage("Class must not be null"); } @Test void getClassLoaderForPrimitive() { assertThat(int.class.getClassLoader()).isNull(); ClassLoader classLoader = ClassLoaderUtils.getClassLoader(int.class); assertThat(classLoader).isSameAs(getClass().getClassLoader()); } @Test void getClassLoaderForWrapperType() { assertThat(Byte.class.getClassLoader()).isNull(); ClassLoader classLoader = ClassLoaderUtils.getClassLoader(Byte.class); assertThat(classLoader).isSameAs(getClass().getClassLoader()); } @Test void getClassLoaderForVoidType() { assertThat(void.class.getClassLoader()).isNull(); ClassLoader classLoader = ClassLoaderUtils.getClassLoader(void.class); assertThat(classLoader).isSameAs(getClass().getClassLoader()); } @Test void getClassLoaderForTestClass() { assertThat(getClass().getClassLoader()).isNotNull(); ClassLoader classLoader = ClassLoaderUtils.getClassLoader(getClass()); assertThat(classLoader).isSameAs(getClass().getClassLoader()); } @Test void getClassLoaderForClassInDifferentClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(getClass())) { var testClass = testClassLoader.loadClass(getClass().getName()); assertThat(testClass.getClassLoader()).isSameAs(testClassLoader); var classLoader = ClassLoaderUtils.getClassLoader(testClass); assertThat(classLoader).isSameAs(testClassLoader); } } @Test void getDefaultClassLoaderWithExplicitContextClassLoader() { var original = Thread.currentThread().getContextClassLoader(); var mock = mock(ClassLoader.class); Thread.currentThread().setContextClassLoader(mock); try { assertSame(mock, ClassLoaderUtils.getDefaultClassLoader()); } finally { Thread.currentThread().setContextClassLoader(original); } } @Test void getDefaultClassLoaderWithNullContextClassLoader() { var original = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(null); try { assertSame(ClassLoader.getSystemClassLoader(), ClassLoaderUtils.getDefaultClassLoader()); } finally { Thread.currentThread().setContextClassLoader(original); } } @Test void getLocationFromNullFails() { var exception = assertThrows(PreconditionViolationException.class, () -> ClassLoaderUtils.getLocation(null)); assertEquals("object must not be null", exception.getMessage()); } @Test void getLocationFromVariousObjectsArePresent() { assertTrue(ClassLoaderUtils.getLocation(void.class).isPresent()); assertTrue(ClassLoaderUtils.getLocation(byte.class).isPresent()); assertTrue(ClassLoaderUtils.getLocation(this).isPresent()); assertTrue(ClassLoaderUtils.getLocation("").isPresent()); assertTrue(ClassLoaderUtils.getLocation(0).isPresent()); assertTrue(ClassLoaderUtils.getLocation(Thread.State.RUNNABLE).isPresent()); } } ClassNamePatternFilterUtilsTests.java000066400000000000000000000130151455764576500363000ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import java.util.List; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.util.classes.AExecutionConditionClass; import org.junit.platform.commons.util.classes.ATestExecutionListenerClass; import org.junit.platform.commons.util.classes.AVanillaEmpty; import org.junit.platform.commons.util.classes.BExecutionConditionClass; import org.junit.platform.commons.util.classes.BTestExecutionListenerClass; import org.junit.platform.commons.util.classes.BVanillaEmpty; import org.junit.platform.launcher.TestExecutionListener; /** * Unit tests for {@link ClassNamePatternFilterUtils}. * * @since 1.7 */ @TestInstance(Lifecycle.PER_CLASS) class ClassNamePatternFilterUtilsTests { //@formatter:off @ValueSource(strings = { "org.junit.jupiter.*", "org.junit.platform.*.NonExistentClass", "*.NonExistentClass*", "*NonExistentClass*", "AExecutionConditionClass, BExecutionConditionClass" }) //@formatter:on @ParameterizedTest void neverExcludedConditions(String pattern) { List executionConditions = List.of(new AExecutionConditionClass(), new BExecutionConditionClass()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .hasSize(2); } //@formatter:off @ValueSource(strings = { "org.junit.platform.*", "*.platform.*", "*", "*AExecutionConditionClass, *BExecutionConditionClass", "*ExecutionConditionClass" }) //@formatter:on @ParameterizedTest void alwaysExcludedConditions(String pattern) { List executionConditions = List.of(new AExecutionConditionClass(), new BExecutionConditionClass()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .isEmpty(); } //@formatter:off @ValueSource(strings = { "org.junit.jupiter.*", "org.junit.platform.*.NonExistentClass", "*.NonExistentClass*", "*NonExistentClass*", "ATestExecutionListenerClass, BTestExecutionListenerClass" }) //@formatter:on @ParameterizedTest void neverExcludedListeners(String pattern) { List executionConditions = List.of(new ATestExecutionListenerClass(), new BTestExecutionListenerClass()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .hasSize(2); } //@formatter:off @ValueSource(strings = { "org.junit.platform.*", "*.platform.*", "*", "*ATestExecutionListenerClass, *BTestExecutionListenerClass", "*TestExecutionListenerClass" }) //@formatter:on @ParameterizedTest void alwaysExcludedListeners(String pattern) { List executionConditions = List.of(new ATestExecutionListenerClass(), new BTestExecutionListenerClass()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .isEmpty(); } //@formatter:off @ValueSource(strings = { "org.junit.jupiter.*", "org.junit.platform.*.NonExistentClass", "*.NonExistentClass*", "*NonExistentClass*", "AVanillaEmpty, BVanillaEmpty" }) //@formatter:on @ParameterizedTest void neverExcludedClass(String pattern) { var executionConditions = List.of(new AVanillaEmpty(), new BVanillaEmpty()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .hasSize(2); } //@formatter:off @ValueSource(strings = { "org.junit.platform.*", "*.platform.*", "*", "*AVanillaEmpty, *BVanillaEmpty", "*VanillaEmpty" }) //@formatter:on @ParameterizedTest void alwaysExcludedClass(String pattern) { var executionConditions = List.of(new AVanillaEmpty(), new BVanillaEmpty()); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClasses(pattern)) // .isEmpty(); } //@formatter:off @ValueSource(strings = { "org.junit.jupiter.*", "org.junit.platform.*.NonExistentClass", "*.NonExistentClass*", "*NonExistentClass*", "AVanillaEmpty, BVanillaEmpty" }) //@formatter:on @ParameterizedTest void neverExcludedClassName(String pattern) { var executionConditions = List.of("org.junit.platform.commons.util.classes.AVanillaEmpty", "org.junit.platform.commons.util.classes.BVanillaEmpty"); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClassNames(pattern)) // .hasSize(2); } //@formatter:off @ValueSource(strings = { "org.junit.platform.*", "*.platform.*", "*", "*AVanillaEmpty, *BVanillaEmpty", "*VanillaEmpty" }) //@formatter:on @ParameterizedTest void alwaysExcludedClassName(String pattern) { var executionConditions = List.of("org.junit.platform.commons.util.classes.AVanillaEmpty", "org.junit.platform.commons.util.classes.BVanillaEmpty"); assertThat(executionConditions).filteredOn(ClassNamePatternFilterUtils.excludeMatchingClassNames(pattern)) // .isEmpty(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/ClassUtilsTests.java000066400000000000000000000030201455764576500330450ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.commons.util.ClassUtils.nullSafeToString; import org.junit.jupiter.api.Test; /** * Unit tests for {@link ClassUtils}. * * @since 1.0 */ class ClassUtilsTests { @Test void nullSafeToStringWithDefaultMapper() { assertEquals("", nullSafeToString((Class[]) null)); assertEquals("", nullSafeToString()); assertEquals("java.lang.String", nullSafeToString(String.class)); assertEquals("java.lang.String, java.lang.Integer", nullSafeToString(String.class, Integer.class)); assertEquals("java.lang.String, null, java.lang.Integer", nullSafeToString(String.class, null, Integer.class)); } @Test void nullSafeToStringWithCustomMapper() { assertEquals("", nullSafeToString(Class::getSimpleName, (Class[]) null)); assertEquals("", nullSafeToString(Class::getSimpleName)); assertEquals("String", nullSafeToString(Class::getSimpleName, String.class)); assertEquals("String, Integer", nullSafeToString(Class::getSimpleName, String.class, Integer.class)); assertEquals("String, null, Integer", nullSafeToString(Class::getSimpleName, String.class, null, Integer.class)); } } ClasspathScannerTests.java000066400000000000000000000364121455764576500341470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.platform.commons.test.ConcurrencyTestingUtils.executeConcurrently; import java.io.IOException; import java.lang.module.ModuleFinder; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.FileSystemNotFoundException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.spi.ToolProvider; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.LogRecordListener; /** * Unit tests for {@link ClasspathScanner}. * * @since 1.0 */ @TrackLogRecords class ClasspathScannerTests { private static final ClassFilter allClasses = ClassFilter.of(type -> true); private final List> loadedClasses = new ArrayList<>(); private final BiFunction>> trackingClassLoader = (name, classLoader) -> ReflectionUtils.tryToLoadClass(name, classLoader).ifSuccess(loadedClasses::add); private final ClasspathScanner classpathScanner = new ClasspathScanner(ClassLoaderUtils::getDefaultClassLoader, trackingClassLoader); @Test void scanForClassesInClasspathRootWhenMalformedClassnameInternalErrorOccursWithNullDetailedMessage( LogRecordListener listener) throws Exception { Predicate> malformedClassNameSimulationFilter = clazz -> { if (clazz.getSimpleName().equals(ClassForMalformedClassNameSimulation.class.getSimpleName())) { throw new InternalError(); } return true; }; assertClassesScannedWhenExceptionIsThrown(malformedClassNameSimulationFilter); assertDebugMessageLogged(listener, "Failed to load java.lang.Class for path .+ during classpath scanning."); } @Test void scanForClassesInClasspathRootWhenMalformedClassnameInternalErrorOccurs(LogRecordListener listener) throws Exception { Predicate> malformedClassNameSimulationFilter = clazz -> { if (clazz.getSimpleName().equals(ClassForMalformedClassNameSimulation.class.getSimpleName())) { throw new InternalError("Malformed class name"); } return true; }; assertClassesScannedWhenExceptionIsThrown(malformedClassNameSimulationFilter); assertDebugMessageLogged(listener, "The java.lang.Class loaded from path .+ has a malformed class name .+"); } @Test void scanForClassesInClasspathRootWhenOtherInternalErrorOccurs(LogRecordListener listener) throws Exception { Predicate> otherInternalErrorSimulationFilter = clazz -> { if (clazz.getSimpleName().equals(ClassForOtherInternalErrorSimulation.class.getSimpleName())) { throw new InternalError("other internal error"); } return true; }; assertClassesScannedWhenExceptionIsThrown(otherInternalErrorSimulationFilter); assertDebugMessageLogged(listener, "Failed to load java.lang.Class for path .+ during classpath scanning."); } @Test void scanForClassesInClasspathRootWhenGenericRuntimeExceptionOccurs(LogRecordListener listener) throws Exception { Predicate> runtimeExceptionSimulationFilter = clazz -> { if (clazz.getSimpleName().equals(ClassForGenericRuntimeExceptionSimulation.class.getSimpleName())) { throw new RuntimeException("a generic exception"); } return true; }; assertClassesScannedWhenExceptionIsThrown(runtimeExceptionSimulationFilter); assertDebugMessageLogged(listener, "Failed to load java.lang.Class for path .+ during classpath scanning."); } private void assertClassesScannedWhenExceptionIsThrown(Predicate> filter) throws Exception { var classFilter = ClassFilter.of(filter); var classes = this.classpathScanner.scanForClassesInClasspathRoot(getTestClasspathRoot(), classFilter); assertThat(classes).hasSizeGreaterThanOrEqualTo(150); } private void assertDebugMessageLogged(LogRecordListener listener, String regex) { // @formatter:off assertThat(listener.stream(ClasspathScanner.class, Level.FINE) .map(LogRecord::getMessage) .filter(m -> m.matches(regex)) ).hasSize(1); // @formatter:on } @Test void scanForClassesInClasspathRootWhenOutOfMemoryErrorOccurs() { Predicate> outOfMemoryErrorSimulationFilter = clazz -> { if (clazz.getSimpleName().equals(ClassForOutOfMemoryErrorSimulation.class.getSimpleName())) { throw new OutOfMemoryError(); } return true; }; var classFilter = ClassFilter.of(outOfMemoryErrorSimulationFilter); assertThrows(OutOfMemoryError.class, () -> this.classpathScanner.scanForClassesInClasspathRoot(getTestClasspathRoot(), classFilter)); } @Test void scanForClassesInClasspathRootWithinJarFile() throws Exception { scanForClassesInClasspathRootWithinJarFile("/jartest.jar"); } @Test void scanForClassesInClasspathRootWithinJarWithSpacesInPath() throws Exception { scanForClassesInClasspathRootWithinJarFile("/folder with spaces/jar test with spaces.jar"); } private void scanForClassesInClasspathRootWithinJarFile(String resourceName) throws Exception { var jarfile = getClass().getResource(resourceName); try (var classLoader = new URLClassLoader(new URL[] { jarfile })) { var classpathScanner = new ClasspathScanner(() -> classLoader, ReflectionUtils::tryToLoadClass); var classes = classpathScanner.scanForClassesInClasspathRoot(jarfile.toURI(), allClasses); var classNames = classes.stream().map(Class::getName).collect(Collectors.toList()); assertThat(classNames).hasSize(3) // .contains("org.junit.platform.jartest.notincluded.NotIncluded", "org.junit.platform.jartest.included.recursive.RecursivelyIncluded", "org.junit.platform.jartest.included.Included"); } } @Test void scanForClassesInPackage() { var classes = classpathScanner.scanForClassesInPackage("org.junit.platform.commons", allClasses); assertThat(classes).hasSizeGreaterThanOrEqualTo(20); assertTrue(classes.contains(NestedClassToBeFound.class)); assertTrue(classes.contains(MemberClassToBeFound.class)); } @Test // #2500 void scanForClassesInPackageWithinModulesSharingNamePrefix(@TempDir Path temp) throws Exception { var moduleSourcePath = Path.of(getClass().getResource("/modules-2500/").toURI()).toString(); run("javac", "--module", "foo,foo.bar", "--module-source-path", moduleSourcePath, "-d", temp.toString()); checkModules2500(ModuleFinder.of(temp)); // exploded modules var foo = temp.resolve("foo.jar"); var bar = temp.resolve("foo.bar.jar"); run("jar", "--create", "--file", foo.toString(), "-C", temp.resolve("foo").toString(), "."); run("jar", "--create", "--file", bar.toString(), "-C", temp.resolve("foo.bar").toString(), "."); checkModules2500(ModuleFinder.of(foo, bar)); // jarred modules System.gc(); // required on Windows in order to release JAR file handles } private static int run(String tool, String... args) { return ToolProvider.findFirst(tool).orElseThrow().run(System.out, System.err, args); } private void checkModules2500(ModuleFinder finder) { var root = "foo.bar"; var before = ModuleFinder.of(); var boot = ModuleLayer.boot(); var configuration = boot.configuration().resolve(before, finder, Set.of(root)); var parent = ClassLoader.getPlatformClassLoader(); var layer = ModuleLayer.defineModulesWithOneLoader(configuration, List.of(boot), parent).layer(); var classpathScanner = new ClasspathScanner(() -> layer.findLoader(root), ReflectionUtils::tryToLoadClass); { var classes = classpathScanner.scanForClassesInPackage("foo", allClasses); var classNames = classes.stream().map(Class::getName).collect(Collectors.toList()); assertThat(classNames).hasSize(2).contains("foo.Foo", "foo.bar.FooBar"); } { var classes = classpathScanner.scanForClassesInPackage("foo.bar", allClasses); var classNames = classes.stream().map(Class::getName).collect(Collectors.toList()); assertThat(classNames).hasSize(1).contains("foo.bar.FooBar"); } } @Test void findAllClassesInPackageWithinJarFileConcurrently() throws Exception { var jarFile = getClass().getResource("/jartest.jar"); var jarUri = URI.create("jar:" + jarFile); try (var classLoader = new URLClassLoader(new URL[] { jarFile })) { var classpathScanner = new ClasspathScanner(() -> classLoader, ReflectionUtils::tryToLoadClass); var results = executeConcurrently(10, () -> classpathScanner.scanForClassesInPackage("org.junit.platform.jartest.included", allClasses)); assertThrows(FileSystemNotFoundException.class, () -> FileSystems.getFileSystem(jarUri), "FileSystem should be closed"); results.forEach(classes -> { assertThat(classes).hasSize(2); var classNames = classes.stream().map(Class::getSimpleName).toList(); assertTrue(classNames.contains("Included")); assertTrue(classNames.contains("RecursivelyIncluded")); }); } } @Test void scanForClassesInDefaultPackage() { var classFilter = ClassFilter.of(this::inDefaultPackage); var classes = classpathScanner.scanForClassesInPackage("", classFilter); assertThat(classes).as("number of classes found in default package").isNotEmpty(); assertTrue(classes.stream().allMatch(this::inDefaultPackage)); assertTrue(classes.stream().anyMatch(clazz -> "DefaultPackageTestCase".equals(clazz.getName()))); } @Test void scanForClassesInPackageWithFilter() { var thisClassOnly = ClassFilter.of(clazz -> clazz == ClasspathScannerTests.class); var classes = classpathScanner.scanForClassesInPackage("org.junit.platform.commons", thisClassOnly); assertSame(ClasspathScannerTests.class, classes.get(0)); } @Test void scanForClassesInPackageForNullBasePackage() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInPackage(null, allClasses)); } @Test void scanForClassesInPackageForWhitespaceBasePackage() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInPackage(" ", allClasses)); } @Test void scanForClassesInPackageForNullClassFilter() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInPackage("org.junit.platform.commons", null)); } @Test void scanForClassesInPackageWhenIOExceptionOccurs() { var scanner = new ClasspathScanner(ThrowingClassLoader::new, ReflectionUtils::tryToLoadClass); var classes = scanner.scanForClassesInPackage("org.junit.platform.commons", allClasses); assertThat(classes).isEmpty(); } @Test void scanForClassesInPackageOnlyLoadsClassesThatAreIncludedByTheClassNameFilter() { Predicate classNameFilter = name -> ClasspathScannerTests.class.getName().equals(name); var classFilter = ClassFilter.of(classNameFilter, type -> true); classpathScanner.scanForClassesInPackage("org.junit.platform.commons", classFilter); assertThat(loadedClasses).containsExactly(ClasspathScannerTests.class); } @Test void findAllClassesInClasspathRoot() throws Exception { var thisClassOnly = ClassFilter.of(clazz -> clazz == ClasspathScannerTests.class); var root = getTestClasspathRoot(); var classes = classpathScanner.scanForClassesInClasspathRoot(root, thisClassOnly); assertSame(ClasspathScannerTests.class, classes.get(0)); } @Test void findAllClassesInDefaultPackageInClasspathRoot() throws Exception { var classFilter = ClassFilter.of(this::inDefaultPackage); var classes = classpathScanner.scanForClassesInClasspathRoot(getTestClasspathRoot(), classFilter); assertEquals(1, classes.size(), "number of classes found in default package"); var testClass = classes.get(0); assertTrue(inDefaultPackage(testClass)); assertEquals("DefaultPackageTestCase", testClass.getName()); } @Test void doesNotLoopInfinitelyWithCircularSymlinks(@TempDir Path tempDir) throws Exception { // Abort if running on Microsoft Windows since we are testing symbolic links assumeFalse(System.getProperty("os.name").toLowerCase().contains("win")); var directory = Files.createDirectory(tempDir.resolve("directory")); var symlink1 = Files.createSymbolicLink(tempDir.resolve("symlink1"), directory); Files.createSymbolicLink(directory.resolve("symlink2"), symlink1); var classes = classpathScanner.scanForClassesInClasspathRoot(symlink1.toUri(), allClasses); assertThat(classes).isEmpty(); } private boolean inDefaultPackage(Class clazz) { // OpenJDK returns NULL for the default package. var pkg = clazz.getPackage(); return pkg == null || "".equals(clazz.getPackage().getName()); } @Test void findAllClassesInClasspathRootWithFilter() throws Exception { var root = getTestClasspathRoot(); var classes = classpathScanner.scanForClassesInClasspathRoot(root, allClasses); assertThat(classes).hasSizeGreaterThanOrEqualTo(20); assertTrue(classes.contains(ClasspathScannerTests.class)); } @Test void findAllClassesInClasspathRootForNullRoot() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInClasspathRoot(null, allClasses)); } @Test void findAllClassesInClasspathRootForNonExistingRoot() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInClasspathRoot(Paths.get("does_not_exist").toUri(), allClasses)); } @Test void findAllClassesInClasspathRootForNullClassFilter() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInClasspathRoot(getTestClasspathRoot(), null)); } @Test void onlyLoadsClassesInClasspathRootThatAreIncludedByTheClassNameFilter() throws Exception { var classFilter = ClassFilter.of(name -> ClasspathScannerTests.class.getName().equals(name), type -> true); var root = getTestClasspathRoot(); classpathScanner.scanForClassesInClasspathRoot(root, classFilter); assertThat(loadedClasses).containsExactly(ClasspathScannerTests.class); } private URI getTestClasspathRoot() throws Exception { var location = getClass().getProtectionDomain().getCodeSource().getLocation(); return location.toURI(); } class MemberClassToBeFound { } static class NestedClassToBeFound { } static class ClassForMalformedClassNameSimulation { } static class ClassForOtherInternalErrorSimulation { } static class ClassForGenericRuntimeExceptionSimulation { } static class ClassForOutOfMemoryErrorSimulation { } private static class ThrowingClassLoader extends ClassLoader { @Override public Enumeration getResources(String name) throws IOException { throw new IOException("Demo I/O error"); } } } CollectionUtilsTests.java000066400000000000000000000224771455764576500340350ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ArgumentConversionException; import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link CollectionUtils}. * * @since 1.0 */ class CollectionUtilsTests { @Test void getOnlyElementWithNullCollection() { var exception = assertThrows(PreconditionViolationException.class, () -> CollectionUtils.getOnlyElement(null)); assertEquals("collection must not be null", exception.getMessage()); } @Test void getOnlyElementWithEmptyCollection() { var exception = assertThrows(PreconditionViolationException.class, () -> CollectionUtils.getOnlyElement(Set.of())); assertEquals("collection must contain exactly one element: []", exception.getMessage()); } @Test void getOnlyElementWithSingleElementCollection() { var expected = new Object(); var actual = CollectionUtils.getOnlyElement(Set.of(expected)); assertSame(expected, actual); } @Test void getOnlyElementWithMultiElementCollection() { var exception = assertThrows(PreconditionViolationException.class, () -> CollectionUtils.getOnlyElement(List.of("foo", "bar"))); assertEquals("collection must contain exactly one element: [foo, bar]", exception.getMessage()); } @Test void toUnmodifiableListThrowsOnMutation() { var numbers = Stream.of(1).collect(toUnmodifiableList()); assertThrows(UnsupportedOperationException.class, numbers::clear); } @ParameterizedTest @ValueSource(classes = { // Stream.class, // DoubleStream.class, // IntStream.class, // LongStream.class, // Collection.class, // Iterable.class, // Iterator.class, // Object[].class, // String[].class, // int[].class, // double[].class, // char[].class // }) void isConvertibleToStreamForSupportedTypes(Class type) { assertThat(CollectionUtils.isConvertibleToStream(type)).isTrue(); } @ParameterizedTest @MethodSource("objectsConvertibleToStreams") void isConvertibleToStreamForSupportedTypesFromObjects(Object object) { assertThat(CollectionUtils.isConvertibleToStream(object.getClass())).isTrue(); } static Stream objectsConvertibleToStreams() { return Stream.of(// Stream.of("cat", "dog"), // DoubleStream.of(42.3), // IntStream.of(99), // LongStream.of(100000000), // Set.of(1, 2, 3), // Arguments.of((Object) new Object[] { 9, 8, 7 }), // new int[] { 5, 10, 15 }// ); } @ParameterizedTest @ValueSource(classes = { // void.class, // Void.class, // Object.class, // Integer.class, // String.class, // int.class, // boolean.class // }) void isConvertibleToStreamForUnsupportedTypes(Class type) { assertThat(CollectionUtils.isConvertibleToStream(type)).isFalse(); } @Test void isConvertibleToStreamForNull() { assertThat(CollectionUtils.isConvertibleToStream(null)).isFalse(); } @Test void toStreamWithNull() { Exception exception = assertThrows(PreconditionViolationException.class, () -> CollectionUtils.toStream(null)); assertThat(exception).hasMessage("Object must not be null"); } @Test void toStreamWithUnsupportedObjectType() { Exception exception = assertThrows(PreconditionViolationException.class, () -> CollectionUtils.toStream("unknown")); assertThat(exception).hasMessage("Cannot convert instance of java.lang.String into a Stream: unknown"); } @Test void toStreamWithExistingStream() { var input = Stream.of("foo"); var result = CollectionUtils.toStream(input); assertThat(result).isSameAs(input); } @Test @SuppressWarnings("unchecked") void toStreamWithDoubleStream() { var input = DoubleStream.of(42.23); var result = (Stream) CollectionUtils.toStream(input); assertThat(result).containsExactly(42.23); } @Test @SuppressWarnings("unchecked") void toStreamWithIntStream() { var input = IntStream.of(23, 42); var result = (Stream) CollectionUtils.toStream(input); assertThat(result).containsExactly(23, 42); } @Test @SuppressWarnings("unchecked") void toStreamWithLongStream() { var input = LongStream.of(23L, 42L); var result = (Stream) CollectionUtils.toStream(input); assertThat(result).containsExactly(23L, 42L); } @Test @SuppressWarnings({ "unchecked", "serial" }) void toStreamWithCollection() { var collectionStreamClosed = new AtomicBoolean(false); Collection input = new ArrayList<>() { { add("foo"); add("bar"); } @Override public Stream stream() { return super.stream().onClose(() -> collectionStreamClosed.set(true)); } }; try (var stream = (Stream) CollectionUtils.toStream(input)) { var result = stream.collect(toList()); assertThat(result).containsExactly("foo", "bar"); } assertThat(collectionStreamClosed.get()).describedAs("collectionStreamClosed").isTrue(); } @Test @SuppressWarnings("unchecked") void toStreamWithIterable() { Iterable input = () -> List.of("foo", "bar").iterator(); var result = (Stream) CollectionUtils.toStream(input); assertThat(result).containsExactly("foo", "bar"); } @Test @SuppressWarnings("unchecked") void toStreamWithIterator() { var input = List.of("foo", "bar").iterator(); var result = (Stream) CollectionUtils.toStream(input); assertThat(result).containsExactly("foo", "bar"); } @Test @SuppressWarnings("unchecked") void toStreamWithArray() { var result = (Stream) CollectionUtils.toStream(new String[] { "foo", "bar" }); assertThat(result).containsExactly("foo", "bar"); } @TestFactory Stream toStreamWithPrimitiveArrays() { //@formatter:off return Stream.of( dynamicTest("boolean[]", () -> toStreamWithPrimitiveArray(new boolean[] { true, false })), dynamicTest("byte[]", () -> toStreamWithPrimitiveArray(new byte[] { 0, Byte.MIN_VALUE, Byte.MAX_VALUE })), dynamicTest("char[]", () -> toStreamWithPrimitiveArray(new char[] { 0, Character.MIN_VALUE, Character.MAX_VALUE })), dynamicTest("double[]", () -> toStreamWithPrimitiveArray(new double[] { 0, Double.MIN_VALUE, Double.MAX_VALUE })), dynamicTest("float[]", () -> toStreamWithPrimitiveArray(new float[] { 0, Float.MIN_VALUE, Float.MAX_VALUE })), dynamicTest("int[]", () -> toStreamWithPrimitiveArray(new int[] { 0, Integer.MIN_VALUE, Integer.MAX_VALUE })), dynamicTest("long[]", () -> toStreamWithPrimitiveArray(new long[] { 0, Long.MIN_VALUE, Long.MAX_VALUE })), dynamicTest("short[]", () -> toStreamWithPrimitiveArray(new short[] { 0, Short.MIN_VALUE, Short.MAX_VALUE })) ); //@formatter:on } private void toStreamWithPrimitiveArray(Object primitiveArray) { assertTrue(primitiveArray.getClass().isArray()); assertTrue(primitiveArray.getClass().getComponentType().isPrimitive()); var result = CollectionUtils.toStream(primitiveArray).toArray(); for (var i = 0; i < result.length; i++) { assertEquals(Array.get(primitiveArray, i), result[i]); } } @ParameterizedTest @CsvSource(delimiter = '|', nullValues = "N/A", textBlock = """ foo,bar,baz | baz,bar,foo foo,bar | bar,foo foo | foo N/A | N/A """) void iteratesListElementsInReverseOrder(@ConvertWith(CommaSeparator.class) List input, @ConvertWith(CommaSeparator.class) List expected) { var result = new ArrayList<>(); CollectionUtils.forEachInReverseOrder(input, result::add); assertEquals(expected, result); } private static class CommaSeparator implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return source == null ? List.of() : List.of(((String) source).split(",")); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java000066400000000000000000000100771455764576500337500ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.commons.util.ExceptionUtils.findNestedThrowables; import static org.junit.platform.commons.util.ExceptionUtils.pruneStackTrace; import static org.junit.platform.commons.util.ExceptionUtils.readStackTrace; import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; import java.io.IOException; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link ExceptionUtils}. * * @since 1.0 */ class ExceptionUtilsTests { @Test void throwAsUncheckedExceptionWithNullException() { assertThrows(PreconditionViolationException.class, () -> throwAsUncheckedException(null)); } @Test void throwAsUncheckedExceptionWithCheckedException() { assertThrows(IOException.class, () -> throwAsUncheckedException(new IOException())); } @Test void throwAsUncheckedExceptionWithUncheckedException() { assertThrows(RuntimeException.class, () -> throwAsUncheckedException(new NumberFormatException())); } @Test void readStackTraceForNullThrowable() { assertThrows(PreconditionViolationException.class, () -> readStackTrace(null)); } @Test void readStackTraceForLocalJUnitException() { try { throw new JUnitException("expected"); } catch (JUnitException e) { // @formatter:off assertThat(readStackTrace(e)) .startsWith(JUnitException.class.getName() + ": expected") .contains("at " + ExceptionUtilsTests.class.getName()); // @formatter:on } } @ParameterizedTest @ValueSource(strings = { "org.junit.", "jdk.internal.reflect.", "sun.reflect." }) void pruneStackTraceOfCallsFromSpecificPackage(String shouldBePruned) { JUnitException exception = new JUnitException("expected"); pruneStackTrace(exception, List.of()); assertThat(exception.getStackTrace()) // .noneMatch(element -> element.toString().contains(shouldBePruned)); } @Test void pruneStackTraceOfAllLauncherCalls() { JUnitException exception = new JUnitException("expected"); pruneStackTrace(exception, List.of()); assertThat(exception.getStackTrace()) // .noneMatch(element -> element.toString().contains("org.junit.platform.launcher.")); } @Test void pruneStackTraceOfEverythingPriorToFirstLauncherCall() { JUnitException exception = new JUnitException("expected"); StackTraceElement[] stackTrace = exception.getStackTrace(); stackTrace[stackTrace.length - 1] = new StackTraceElement("org.example.Class", "method", "file", 123); exception.setStackTrace(stackTrace); pruneStackTrace(exception, List.of()); assertThat(exception.getStackTrace()) // .noneMatch(element -> element.toString().contains("org.example.Class.method(file:123)")); } @Test void findSuppressedExceptionsAndCausesOfThrowable() { Throwable t1 = new Throwable("#1"); Throwable t2 = new Throwable("#2"); Throwable t3 = new Throwable("#3"); Throwable t4 = new Throwable("#4"); Throwable t5 = new Throwable("#5"); t1.initCause(t2); t2.initCause(t3); t1.addSuppressed(t4); t2.addSuppressed(t5); assertThat(findNestedThrowables(t1)) // .extracting(Throwable::getMessage) // .containsExactlyInAnyOrder("#1", "#2", "#3", "#4", "#5"); } @Test void avoidCyclesWhileSearchingForNestedThrowables() { Throwable t1 = new Throwable(); Throwable t2 = new Throwable(t1); Throwable t3 = new Throwable(t1); t1.initCause(t2); t1.addSuppressed(t3); t2.addSuppressed(t3); assertThat(findNestedThrowables(t1)).hasSize(3); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/FunctionUtilsTests.java000066400000000000000000000030551455764576500335750ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.function.Predicate.isEqual; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link FunctionUtils}. * * @since 1.0 */ class FunctionUtilsTests { @Test void whereWithNullFunction() { var exception = assertThrows(PreconditionViolationException.class, () -> FunctionUtils.where(null, o -> true)); assertEquals("function must not be null", exception.getMessage()); } @Test void whereWithNullPredicate() { var exception = assertThrows(PreconditionViolationException.class, () -> FunctionUtils.where(o -> o, null)); assertEquals("predicate must not be null", exception.getMessage()); } @Test void whereWithChecksPredicateAgainstResultOfFunction() { var combinedPredicate = FunctionUtils.where(String::length, isEqual(3)); assertFalse(combinedPredicate.test("fo")); assertTrue(combinedPredicate.test("foo")); assertFalse(combinedPredicate.test("fooo")); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/LruCacheTests.java000066400000000000000000000014101455764576500324460ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import org.junit.jupiter.api.Test; /** * @since 1.6 */ class LruCacheTests { @Test void evictsEldestEntryWhenMaxSizeIsReached() { var cache = new LruCache(1); cache.put(0, 0); cache.put(1, 1); assertThat(cache) // .doesNotContain(entry(0, 0)) // .hasSize(1); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/ModuleUtilsTests.java000066400000000000000000000015011455764576500332270ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * Unit tests for {@link ModuleUtils}. * * @since 1.1 */ class ModuleUtilsTests { @Test void isJavaPlatformModuleSystemAvailable() { boolean expected; try { Class.forName("java.lang.Module"); expected = true; } catch (ClassNotFoundException e) { expected = false; } assertEquals(expected, ModuleUtils.isJavaPlatformModuleSystemAvailable()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/PackageUtilsTests.java000066400000000000000000000070211455764576500333400ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.List; import java.util.function.Function; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.PreconditionViolationException; import org.opentest4j.ValueWrapper; /** * Unit tests for {@link PackageUtils}. * * @since 1.0 */ class PackageUtilsTests { @Test void getAttributeWithNullType() { var exception = assertThrows(PreconditionViolationException.class, () -> PackageUtils.getAttribute(null, p -> "any")); assertEquals("type must not be null", exception.getMessage()); } @Test void getAttributeWithNullFunction() { var exception = assertThrows(PreconditionViolationException.class, () -> PackageUtils.getAttribute(getClass(), (Function) null)); assertEquals("function must not be null", exception.getMessage()); } @Test void getAttributeWithFunctionReturningNullIsEmpty() { assertFalse(PackageUtils.getAttribute(ValueWrapper.class, p -> null).isPresent()); } @Test void getAttributeFromDefaultPackageMemberIsEmpty() throws Exception { var classInDefaultPackage = ReflectionUtils.tryToLoadClass("DefaultPackageTestCase").get(); assertFalse(PackageUtils.getAttribute(classInDefaultPackage, Package::getSpecificationTitle).isPresent()); } @TestFactory List attributesFromValueWrapperClassArePresent() { return List.of( // dynamicTest("getName", isPresent(Package::getName)), dynamicTest("getImplementationTitle", isPresent(Package::getImplementationTitle)), dynamicTest("getImplementationVendor", isPresent(Package::getImplementationVendor)), dynamicTest("getImplementationVersion", isPresent(Package::getImplementationVersion)), dynamicTest("getSpecificationTitle", isPresent(Package::getSpecificationTitle)), dynamicTest("getSpecificationVendor", isPresent(Package::getSpecificationVendor)), dynamicTest("getSpecificationVersion", isPresent(Package::getSpecificationVersion)) // ); } private Executable isPresent(Function function) { return () -> assertTrue(PackageUtils.getAttribute(ValueWrapper.class, function).isPresent()); } @Test void getAttributeWithNullTypeAndName() { var exception = assertThrows(PreconditionViolationException.class, () -> PackageUtils.getAttribute(null, "foo")); assertEquals("type must not be null", exception.getMessage()); } @Test void getAttributeWithNullName() { var exception = assertThrows(PreconditionViolationException.class, () -> PackageUtils.getAttribute(getClass(), (String) null)); assertEquals("name must not be blank", exception.getMessage()); } @Test void getAttributeWithEmptyName() { var exception = assertThrows(PreconditionViolationException.class, () -> PackageUtils.getAttribute(getClass(), "")); assertEquals("name must not be blank", exception.getMessage()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/PreconditionsTests.java000066400000000000000000000172701455764576500336130ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.commons.util.Preconditions.condition; import static org.junit.platform.commons.util.Preconditions.containsNoNullElements; import static org.junit.platform.commons.util.Preconditions.notBlank; import static org.junit.platform.commons.util.Preconditions.notEmpty; import static org.junit.platform.commons.util.Preconditions.notNull; import java.util.Collection; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link Preconditions}. * * @since 1.0 */ class PreconditionsTests { @Test void notNullPassesForNonNullObject() { var object = new Object(); var nonNullObject = notNull(object, "message"); assertSame(object, nonNullObject); } @Test void notNullThrowsForNullObject() { var message = "argument is null"; var exception = assertThrows(PreconditionViolationException.class, () -> notNull(null, message)); assertEquals(message, exception.getMessage()); } @Test void notNullThrowsForNullObjectAndMessageSupplier() { var message = "argument is null"; Object object = null; var exception = assertThrows(PreconditionViolationException.class, () -> notNull(object, () -> message)); assertEquals(message, exception.getMessage()); } @Test void notEmptyPassesForNonEmptyArray() { var array = new String[] { "a", "b", "c" }; var nonEmptyArray = notEmpty(array, () -> "should not fail"); assertSame(array, nonEmptyArray); } @Test void notEmptyPassesForNonEmptyCollection() { Collection collection = List.of("a", "b", "c"); var nonEmptyCollection = notEmpty(collection, () -> "should not fail"); assertSame(collection, nonEmptyCollection); } @Test void notEmptyPassesForArrayWithNullElements() { notEmpty(new String[] { null }, "message"); } @Test void notEmptyPassesForCollectionWithNullElements() { notEmpty(singletonList(null), "message"); } @Test void notEmptyThrowsForNullArray() { var message = "array is empty"; var exception = assertThrows(PreconditionViolationException.class, () -> notEmpty((Object[]) null, message)); assertEquals(message, exception.getMessage()); } @Test void notEmptyThrowsForNullCollection() { var message = "collection is empty"; var exception = assertThrows(PreconditionViolationException.class, () -> notEmpty((Collection) null, message)); assertEquals(message, exception.getMessage()); } @Test void notEmptyThrowsForEmptyArray() { var message = "array is empty"; var exception = assertThrows(PreconditionViolationException.class, () -> notEmpty(new Object[0], message)); assertEquals(message, exception.getMessage()); } @Test void notEmptyThrowsForEmptyCollection() { var message = "collection is empty"; var exception = assertThrows(PreconditionViolationException.class, () -> notEmpty(List.of(), message)); assertEquals(message, exception.getMessage()); } @Test void containsNoNullElementsPassesForArrayThatIsNullOrEmpty() { containsNoNullElements((Object[]) null, "array is null"); containsNoNullElements((Object[]) null, () -> "array is null"); containsNoNullElements(new Object[0], "array is empty"); containsNoNullElements(new Object[0], () -> "array is empty"); } @Test void containsNoNullElementsPassesForCollectionThatIsNullOrEmpty() { containsNoNullElements((List) null, "collection is null"); containsNoNullElements(List.of(), "collection is empty"); containsNoNullElements((List) null, () -> "collection is null"); containsNoNullElements(List.of(), () -> "collection is empty"); } @Test void containsNoNullElementsPassesForArrayContainingNonNullElements() { var input = new String[] { "a", "b", "c" }; var output = containsNoNullElements(input, "message"); assertSame(input, output); } @Test void containsNoNullElementsPassesForCollectionContainingNonNullElements() { var input = List.of("a", "b", "c"); var output = containsNoNullElements(input, "message"); assertSame(input, output); output = containsNoNullElements(input, () -> "message"); assertSame(input, output); } @Test void containsNoNullElementsThrowsForArrayContainingNullElements() { var message = "array contains null elements"; Object[] array = { new Object(), null, new Object() }; var exception = assertThrows(PreconditionViolationException.class, () -> containsNoNullElements(array, message)); assertEquals(message, exception.getMessage()); } @Test void containsNoNullElementsThrowsForCollectionContainingNullElements() { var message = "collection contains null elements"; var exception = assertThrows(PreconditionViolationException.class, () -> containsNoNullElements(singletonList(null), message)); assertEquals(message, exception.getMessage()); } @Test void notBlankPassesForNonBlankString() { var string = "abc"; var nonBlankString = notBlank(string, "message"); assertSame(string, nonBlankString); } @Test void notBlankThrowsForNullString() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank(null, message)); assertEquals(message, exception.getMessage()); } @Test void notBlankThrowsForNullStringWithMessageSupplier() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank(null, () -> message)); assertEquals(message, exception.getMessage()); } @Test void notBlankThrowsForEmptyString() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank("", message)); assertEquals(message, exception.getMessage()); } @Test void notBlankThrowsForEmptyStringWithMessageSupplier() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank("", () -> message)); assertEquals(message, exception.getMessage()); } @Test void notBlankThrowsForBlankString() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank(" ", message)); assertEquals(message, exception.getMessage()); } @Test void notBlankThrowsForBlankStringWithMessageSupplier() { var message = "string shouldn't be blank"; var exception = assertThrows(PreconditionViolationException.class, () -> notBlank(" ", () -> message)); assertEquals(message, exception.getMessage()); } @Test void conditionPassesForTruePredicate() { condition(true, "error message"); } @Test void conditionPassesForTruePredicateWithMessageSupplier() { condition(true, () -> "error message"); } @Test void conditionThrowsForFalsePredicate() { var message = "condition does not hold"; var exception = assertThrows(PreconditionViolationException.class, () -> condition(false, message)); assertEquals(message, exception.getMessage()); } @Test void conditionThrowsForFalsePredicateWithMessageSupplier() { var message = "condition does not hold"; var exception = assertThrows(PreconditionViolationException.class, () -> condition(false, () -> message)); assertEquals(message, exception.getMessage()); } } ReflectionUtilsTests.java000066400000000000000000002217761455764576500340370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static java.time.Duration.ofMillis; import static java.util.Arrays.stream; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.function.Try.success; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.util.ReflectionUtils.findFields; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.commons.util.ReflectionUtils.invokeMethod; import static org.junit.platform.commons.util.ReflectionUtils.readFieldValue; import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtilsTests.ClassWithNestedClasses.Nested1; import org.junit.platform.commons.util.ReflectionUtilsTests.ClassWithNestedClasses.Nested2; import org.junit.platform.commons.util.ReflectionUtilsTests.ClassWithNestedClasses.Nested3; import org.junit.platform.commons.util.ReflectionUtilsTests.Interface45.Nested5; import org.junit.platform.commons.util.ReflectionUtilsTests.InterfaceWithNestedClass.Nested4; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.InnerClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.InnerClass.RecursiveInnerInnerClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.InnerSiblingClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.RecursiveInnerClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.StaticNestedClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClass.StaticNestedSiblingClass; import org.junit.platform.commons.util.ReflectionUtilsTests.OuterClassImplementingInterface.InnerClassImplementingInterface; import org.junit.platform.commons.util.classes.CustomType; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateBeforeMethod; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateTempDirField; import org.junit.platform.commons.util.pkg1.subpkg.SubclassWithNonStaticPackagePrivateBeforeMethod; import org.junit.platform.commons.util.pkg1.subpkg.SubclassWithNonStaticPackagePrivateTempDirField; /** * Unit tests for {@link ReflectionUtils}. * * @since 1.0 */ class ReflectionUtilsTests { private static final Predicate isFooMethod = method -> method.getName().equals("foo"); private static final Predicate methodContains1 = method -> method.getName().contains("1"); private static final Predicate methodContains2 = method -> method.getName().contains("2"); private static final Predicate methodContains4 = method -> method.getName().contains("4"); private static final Predicate methodContains5 = method -> method.getName().contains("5"); @Test void isPublic() throws Exception { assertTrue(ReflectionUtils.isPublic(PublicClass.class)); assertTrue(ReflectionUtils.isPublic(PublicClass.class.getMethod("publicMethod"))); assertFalse(ReflectionUtils.isPublic(PrivateClass.class)); assertFalse(ReflectionUtils.isPublic(PrivateClass.class.getDeclaredMethod("privateMethod"))); assertFalse(ReflectionUtils.isPublic(ProtectedClass.class)); assertFalse(ReflectionUtils.isPublic(ProtectedClass.class.getDeclaredMethod("protectedMethod"))); assertFalse(ReflectionUtils.isPublic(PackageVisibleClass.class)); assertFalse(ReflectionUtils.isPublic(PackageVisibleClass.class.getDeclaredMethod("packageVisibleMethod"))); } @Test void isPrivate() throws Exception { assertTrue(ReflectionUtils.isPrivate(PrivateClass.class)); assertTrue(ReflectionUtils.isPrivate(PrivateClass.class.getDeclaredMethod("privateMethod"))); assertFalse(ReflectionUtils.isPrivate(PublicClass.class)); assertFalse(ReflectionUtils.isPrivate(PublicClass.class.getMethod("publicMethod"))); assertFalse(ReflectionUtils.isPrivate(ProtectedClass.class)); assertFalse(ReflectionUtils.isPrivate(ProtectedClass.class.getDeclaredMethod("protectedMethod"))); assertFalse(ReflectionUtils.isPrivate(PackageVisibleClass.class)); assertFalse(ReflectionUtils.isPrivate(PackageVisibleClass.class.getDeclaredMethod("packageVisibleMethod"))); } @Test void isNotPrivate() throws Exception { assertTrue(ReflectionUtils.isNotPrivate(PublicClass.class)); assertTrue(ReflectionUtils.isNotPrivate(PublicClass.class.getDeclaredMethod("publicMethod"))); assertTrue(ReflectionUtils.isNotPrivate(ProtectedClass.class)); assertTrue(ReflectionUtils.isNotPrivate(ProtectedClass.class.getDeclaredMethod("protectedMethod"))); assertTrue(ReflectionUtils.isNotPrivate(PackageVisibleClass.class)); assertTrue(ReflectionUtils.isNotPrivate(PackageVisibleClass.class.getDeclaredMethod("packageVisibleMethod"))); assertFalse(ReflectionUtils.isNotPrivate(PrivateClass.class.getDeclaredMethod("privateMethod"))); } @Test void isAbstract() throws Exception { assertTrue(ReflectionUtils.isAbstract(AbstractClass.class)); assertTrue(ReflectionUtils.isAbstract(AbstractClass.class.getDeclaredMethod("abstractMethod"))); assertFalse(ReflectionUtils.isAbstract(PublicClass.class)); assertFalse(ReflectionUtils.isAbstract(PublicClass.class.getDeclaredMethod("publicMethod"))); } @Test void isStatic() throws Exception { assertTrue(ReflectionUtils.isStatic(StaticClass.class)); assertTrue(ReflectionUtils.isStatic(StaticClass.class.getDeclaredMethod("staticMethod"))); assertFalse(ReflectionUtils.isStatic(PublicClass.class)); assertFalse(ReflectionUtils.isStatic(PublicClass.class.getDeclaredMethod("publicMethod"))); } @Test void isNotStatic() throws Exception { assertTrue(ReflectionUtils.isNotStatic(PublicClass.class)); assertTrue(ReflectionUtils.isNotStatic(PublicClass.class.getDeclaredMethod("publicMethod"))); assertFalse(ReflectionUtils.isNotStatic(StaticClass.class)); assertFalse(ReflectionUtils.isNotStatic(StaticClass.class.getDeclaredMethod("staticMethod"))); } @Test void isFinal() throws Exception { assertTrue(ReflectionUtils.isFinal(FinalClass.class)); assertTrue(ReflectionUtils.isFinal(FinalClass.class.getDeclaredMethod("finalMethod"))); assertFalse(ReflectionUtils.isFinal(PublicClass.class)); assertFalse(ReflectionUtils.isFinal(PublicClass.class.getDeclaredMethod("publicMethod"))); } @Test void isNotFinal() throws Exception { assertTrue(ReflectionUtils.isNotFinal(PublicClass.class)); assertTrue(ReflectionUtils.isNotFinal(PublicClass.class.getDeclaredMethod("publicMethod"))); assertFalse(ReflectionUtils.isNotFinal(FinalClass.class)); assertFalse(ReflectionUtils.isNotFinal(FinalClass.class.getDeclaredMethod("finalMethod"))); } @Test void returnsVoid() throws Exception { Class clazz = ClassWithVoidAndNonVoidMethods.class; assertTrue(ReflectionUtils.returnsVoid(clazz.getDeclaredMethod("voidMethod"))); assertFalse(ReflectionUtils.returnsVoid(clazz.getDeclaredMethod("methodReturningVoidReference"))); assertFalse(ReflectionUtils.returnsVoid(clazz.getDeclaredMethod("methodReturningObject"))); assertFalse(ReflectionUtils.returnsVoid(clazz.getDeclaredMethod("methodReturningPrimitive"))); } @Test void getAllAssignmentCompatibleClassesWithNullClass() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getAllAssignmentCompatibleClasses(null)); } @Test void getAllAssignmentCompatibleClasses() { var superclasses = ReflectionUtils.getAllAssignmentCompatibleClasses(B.class); assertThat(superclasses).containsExactly(B.class, InterfaceC.class, InterfaceA.class, InterfaceB.class, A.class, InterfaceD.class, Object.class); assertTrue(superclasses.stream().allMatch(clazz -> clazz.isAssignableFrom(B.class))); } @Test void newInstance() { // @formatter:off assertThat(ReflectionUtils.newInstance(C.class, "one", "two")).isNotNull(); assertThat(ReflectionUtils.newInstance(C.class)).isNotNull(); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.newInstance(C.class, "one", null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.newInstance(C.class, null, "two")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.newInstance(C.class, null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.newInstance(C.class, ((Object[]) null))); var exception = assertThrows(RuntimeException.class, () -> ReflectionUtils.newInstance(Exploder.class)); assertThat(exception).hasMessage("boom"); // @formatter:on } @Test @SuppressWarnings("deprecation") void readFieldValueOfNonexistentStaticField() { assertThat(readFieldValue(MyClass.class, "doesNotExist", null)).isNotPresent(); assertThat(readFieldValue(MySubClass.class, "staticField", null)).isNotPresent(); } @Test void tryToReadFieldValueOfNonexistentStaticField() { assertThrows(NoSuchFieldException.class, () -> tryToReadFieldValue(MyClass.class, "doesNotExist", null).get()); assertThrows(NoSuchFieldException.class, () -> tryToReadFieldValue(MySubClass.class, "staticField", null).get()); } @Test @SuppressWarnings("deprecation") void readFieldValueOfNonexistentInstanceField() { assertThat(readFieldValue(MyClass.class, "doesNotExist", new MyClass(42))).isNotPresent(); assertThat(readFieldValue(MyClass.class, "doesNotExist", new MySubClass(42))).isNotPresent(); } @Test void tryToReadFieldValueOfNonexistentInstanceField() { assertThrows(NoSuchFieldException.class, () -> tryToReadFieldValue(MyClass.class, "doesNotExist", new MyClass(42)).get()); assertThrows(NoSuchFieldException.class, () -> tryToReadFieldValue(MyClass.class, "doesNotExist", new MySubClass(42)).get()); } @Test @SuppressWarnings("deprecation") void readFieldValueOfExistingStaticField() throws Exception { assertThat(readFieldValue(MyClass.class, "staticField", null)).contains(42); var field = MyClass.class.getDeclaredField("staticField"); assertThat(readFieldValue(field)).contains(42); assertThat(readFieldValue(field, null)).contains(42); } @Test void tryToReadFieldValueOfExistingStaticField() throws Exception { assertThat(tryToReadFieldValue(MyClass.class, "staticField", null).get()).isEqualTo(42); var field = MyClass.class.getDeclaredField("staticField"); assertThat(tryToReadFieldValue(field).get()).isEqualTo(42); assertThat(tryToReadFieldValue(field, null).get()).isEqualTo(42); } @Test @SuppressWarnings("deprecation") void readFieldValueOfExistingInstanceField() throws Exception { var instance = new MyClass(42); assertThat(readFieldValue(MyClass.class, "instanceField", instance)).contains(42); var field = MyClass.class.getDeclaredField("instanceField"); assertThat(readFieldValue(field, instance)).contains(42); } @Test @SuppressWarnings("deprecation") void attemptToReadFieldValueOfExistingInstanceFieldAsStaticField() throws Exception { var field = MyClass.class.getDeclaredField("instanceField"); Exception exception = assertThrows(PreconditionViolationException.class, () -> readFieldValue(field, null)); assertThat(exception)// .hasMessageStartingWith("Cannot read non-static field")// .hasMessageEndingWith("on a null instance."); } @Test void tryToReadFieldValueOfExistingInstanceField() throws Exception { var instance = new MyClass(42); assertThat(tryToReadFieldValue(MyClass.class, "instanceField", instance).get()).isEqualTo(42); var field = MyClass.class.getDeclaredField("instanceField"); assertThat(tryToReadFieldValue(field, instance).get()).isEqualTo(42); assertThrows(PreconditionViolationException.class, () -> tryToReadFieldValue(field, null).get()); } @Nested class IsClassAssignableToClassTests { @Test void isAssignableToForNullSourceType() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> ReflectionUtils.isAssignableTo(null, getClass()))// .withMessage("source type must not be null"); } @Test void isAssignableToForPrimitiveSourceType() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> ReflectionUtils.isAssignableTo(int.class, Integer.class))// .withMessage("source type must not be a primitive type"); } @Test void isAssignableToForNullTargetType() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> ReflectionUtils.isAssignableTo(getClass(), null))// .withMessage("target type must not be null"); } @Test void isAssignableTo() { // Reference Types assertTrue(ReflectionUtils.isAssignableTo(String.class, Object.class)); assertTrue(ReflectionUtils.isAssignableTo(String.class, CharSequence.class)); assertTrue(ReflectionUtils.isAssignableTo(String.class, String.class)); assertTrue(ReflectionUtils.isAssignableTo(Integer.class, Number.class)); assertTrue(ReflectionUtils.isAssignableTo(Integer.class, Integer.class)); assertFalse(ReflectionUtils.isAssignableTo(Object.class, String.class)); assertFalse(ReflectionUtils.isAssignableTo(CharSequence.class, String.class)); assertFalse(ReflectionUtils.isAssignableTo(Number.class, Integer.class)); // Arrays assertTrue(ReflectionUtils.isAssignableTo(int[].class, int[].class)); assertTrue(ReflectionUtils.isAssignableTo(double[].class, double[].class)); assertTrue(ReflectionUtils.isAssignableTo(double[].class, Object.class)); assertTrue(ReflectionUtils.isAssignableTo(String[].class, Object.class)); assertTrue(ReflectionUtils.isAssignableTo(String[].class, Object[].class)); assertTrue(ReflectionUtils.isAssignableTo(String[].class, String[].class)); // Wrappers to Primitives assertTrue(ReflectionUtils.isAssignableTo(Integer.class, int.class)); assertTrue(ReflectionUtils.isAssignableTo(Boolean.class, boolean.class)); // Widening Conversions from Wrappers to Primitives assertTrue(ReflectionUtils.isAssignableTo(Integer.class, long.class)); assertTrue(ReflectionUtils.isAssignableTo(Float.class, double.class)); assertTrue(ReflectionUtils.isAssignableTo(Byte.class, double.class)); // Widening Conversions from Wrappers to Wrappers (not supported by Java) assertFalse(ReflectionUtils.isAssignableTo(Integer.class, Long.class)); assertFalse(ReflectionUtils.isAssignableTo(Float.class, Double.class)); assertFalse(ReflectionUtils.isAssignableTo(Byte.class, Double.class)); // Narrowing Conversions assertFalse(ReflectionUtils.isAssignableTo(Integer.class, char.class)); assertFalse(ReflectionUtils.isAssignableTo(Long.class, byte.class)); assertFalse(ReflectionUtils.isAssignableTo(Long.class, int.class)); } } @Nested class IsObjectAssignableToClassTests { @Test void isAssignableToForNullClass() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.isAssignableTo(new Object(), null)); } @Test void isAssignableTo() { // Reference Types assertTrue(ReflectionUtils.isAssignableTo("string", String.class)); assertTrue(ReflectionUtils.isAssignableTo("string", CharSequence.class)); assertTrue(ReflectionUtils.isAssignableTo("string", Object.class)); assertFalse(ReflectionUtils.isAssignableTo(new Object(), String.class)); assertFalse(ReflectionUtils.isAssignableTo(Integer.valueOf("1"), StringBuilder.class)); assertFalse(ReflectionUtils.isAssignableTo(new StringBuilder(), String.class)); // Arrays assertTrue(ReflectionUtils.isAssignableTo(new int[0], int[].class)); assertTrue(ReflectionUtils.isAssignableTo(new double[0], Object.class)); assertTrue(ReflectionUtils.isAssignableTo(new String[0], String[].class)); assertTrue(ReflectionUtils.isAssignableTo(new String[0], Object.class)); // Primitive Types assertTrue(ReflectionUtils.isAssignableTo(1, int.class)); assertTrue(ReflectionUtils.isAssignableTo(Long.valueOf("1"), long.class)); assertTrue(ReflectionUtils.isAssignableTo(Boolean.TRUE, boolean.class)); // Widening Conversions to Primitives assertTrue(ReflectionUtils.isAssignableTo(1, long.class)); assertTrue(ReflectionUtils.isAssignableTo(1f, double.class)); assertTrue(ReflectionUtils.isAssignableTo((byte) 1, double.class)); // Widening Conversions to Wrappers (not supported by Java) assertFalse(ReflectionUtils.isAssignableTo(1, Long.class)); assertFalse(ReflectionUtils.isAssignableTo(1f, Double.class)); assertFalse(ReflectionUtils.isAssignableTo((byte) 1, Double.class)); // Narrowing Conversions assertFalse(ReflectionUtils.isAssignableTo(1, char.class)); assertFalse(ReflectionUtils.isAssignableTo(1L, byte.class)); assertFalse(ReflectionUtils.isAssignableTo(1L, int.class)); } @Test void isAssignableToForNullObject() { assertTrue(ReflectionUtils.isAssignableTo((Object) null, Object.class)); assertTrue(ReflectionUtils.isAssignableTo((Object) null, String.class)); assertTrue(ReflectionUtils.isAssignableTo((Object) null, Long.class)); assertTrue(ReflectionUtils.isAssignableTo((Object) null, Character[].class)); } @Test void isAssignableToForNullObjectAndPrimitive() { assertFalse(ReflectionUtils.isAssignableTo((Object) null, byte.class)); assertFalse(ReflectionUtils.isAssignableTo((Object) null, int.class)); assertFalse(ReflectionUtils.isAssignableTo((Object) null, long.class)); assertFalse(ReflectionUtils.isAssignableTo((Object) null, boolean.class)); } } @Test void wideningConversion() { // byte assertTrue(ReflectionUtils.isWideningConversion(byte.class, short.class)); assertTrue(ReflectionUtils.isWideningConversion(byte.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(byte.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(byte.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(byte.class, double.class)); // Byte assertTrue(ReflectionUtils.isWideningConversion(Byte.class, short.class)); assertTrue(ReflectionUtils.isWideningConversion(Byte.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(Byte.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(Byte.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(Byte.class, double.class)); // short assertTrue(ReflectionUtils.isWideningConversion(short.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(short.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(short.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(short.class, double.class)); // Short assertTrue(ReflectionUtils.isWideningConversion(Short.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(Short.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(Short.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(Short.class, double.class)); // char assertTrue(ReflectionUtils.isWideningConversion(char.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(char.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(char.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(char.class, double.class)); // Character assertTrue(ReflectionUtils.isWideningConversion(Character.class, int.class)); assertTrue(ReflectionUtils.isWideningConversion(Character.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(Character.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(Character.class, double.class)); // int assertTrue(ReflectionUtils.isWideningConversion(int.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(int.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(int.class, double.class)); // Integer assertTrue(ReflectionUtils.isWideningConversion(Integer.class, long.class)); assertTrue(ReflectionUtils.isWideningConversion(Integer.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(Integer.class, double.class)); // long assertTrue(ReflectionUtils.isWideningConversion(long.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(long.class, double.class)); // Long assertTrue(ReflectionUtils.isWideningConversion(Long.class, float.class)); assertTrue(ReflectionUtils.isWideningConversion(Long.class, double.class)); // float assertTrue(ReflectionUtils.isWideningConversion(float.class, double.class)); // Float assertTrue(ReflectionUtils.isWideningConversion(Float.class, double.class)); // double and Double --> nothing to test // Unsupported assertFalse(ReflectionUtils.isWideningConversion(int.class, byte.class)); // narrowing assertFalse(ReflectionUtils.isWideningConversion(float.class, int.class)); // narrowing assertFalse(ReflectionUtils.isWideningConversion(int.class, int.class)); // direct match assertFalse(ReflectionUtils.isWideningConversion(String.class, int.class)); // neither a primitive nor a wrapper } @Test void invokeMethodPreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> invokeMethod(null, new Object())); assertThrows(PreconditionViolationException.class, () -> invokeMethod(Object.class.getMethod("hashCode"), null)); // @formatter:on } @Test void invokePublicMethod() throws Exception { var tracker = new InvocationTracker(); invokeMethod(InvocationTracker.class.getDeclaredMethod("publicMethod"), tracker); assertTrue(tracker.publicMethodInvoked); } @Test void invokePrivateMethod() throws Exception { var tracker = new InvocationTracker(); invokeMethod(InvocationTracker.class.getDeclaredMethod("privateMethod"), tracker); assertTrue(tracker.privateMethodInvoked); } @Test void invokePublicStaticMethod() throws Exception { invokeMethod(InvocationTracker.class.getDeclaredMethod("publicStaticMethod"), null); assertTrue(InvocationTracker.publicStaticMethodInvoked); } @Test void invokePrivateStaticMethod() throws Exception { invokeMethod(InvocationTracker.class.getDeclaredMethod("privateStaticMethod"), null); assertTrue(InvocationTracker.privateStaticMethodInvoked); } @Test void tryToLoadClassPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass(null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass("")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass(" ")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass(null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass(getClass().getName(), null)); } @Test @SuppressWarnings("deprecation") void loadClassWhenClassNotFoundException() { assertThat(ReflectionUtils.loadClass("foo.bar.EnigmaClassThatDoesNotExist")).isEmpty(); } @Test void tryToLoadClassWhenClassNotFoundException() { assertThrows(ClassNotFoundException.class, () -> ReflectionUtils.tryToLoadClass("foo.bar.EnigmaClassThatDoesNotExist").get()); } @Test void tryToLoadClassFailsWithinReasonableTimeForInsanelyLargeAndInvalidMultidimensionalPrimitiveArrayName() { // Create a class name of the form int[][][]...[][][]X String className = IntStream.rangeClosed(1, 20_000)// .mapToObj(i -> "[]")// .collect(joining("", "int", "X")); // The following should ideally fail in less than 50ms. So we just make // sure it fails in less than 500ms in order to (hopefully) allow the // test to pass on CI servers with limited resources. assertTimeoutPreemptively(ofMillis(500), () -> assertThrows(ClassNotFoundException.class, () -> ReflectionUtils.tryToLoadClass(className).get())); } @Test @SuppressWarnings("deprecation") void loadClass() { var optional = ReflectionUtils.loadClass(Integer.class.getName()); assertThat(optional).contains(Integer.class); } @Test void tryToLoadClass() { assertThat(ReflectionUtils.tryToLoadClass(Integer.class.getName())).isEqualTo(success(Integer.class)); } @Test void tryToLoadClassTrimsClassName() { assertThat(ReflectionUtils.tryToLoadClass(" " + Integer.class.getName() + "\t")).isEqualTo( success(Integer.class)); } @Test void tryToLoadClassForPrimitive() { assertThat(ReflectionUtils.tryToLoadClass(int.class.getName())).isEqualTo(success(int.class)); } @Test void tryToLoadClassForPrimitiveArray() { assertThat(ReflectionUtils.tryToLoadClass(int[].class.getName())).isEqualTo(success(int[].class)); } @Test void tryToLoadClassForPrimitiveArrayUsingSourceCodeSyntax() { assertThat(ReflectionUtils.tryToLoadClass("int[]")).isEqualTo(success(int[].class)); } @Test void tryToLoadClassForObjectArray() { assertThat(ReflectionUtils.tryToLoadClass(String[].class.getName())).isEqualTo(success(String[].class)); } @Test void tryToLoadClassForObjectArrayUsingSourceCodeSyntax() { assertThat(ReflectionUtils.tryToLoadClass("java.lang.String[]")).isEqualTo(success(String[].class)); } @Test void tryToLoadClassForTwoDimensionalPrimitiveArray() { assertThat(ReflectionUtils.tryToLoadClass(int[][].class.getName())).isEqualTo(success(int[][].class)); } @Test void tryToLoadClassForTwoDimensionaldimensionalPrimitiveArrayUsingSourceCodeSyntax() { assertThat(ReflectionUtils.tryToLoadClass("int[][]")).isEqualTo(success(int[][].class)); } @Test void tryToLoadClassForMultidimensionalPrimitiveArray() { assertThat(ReflectionUtils.tryToLoadClass(int[][][][][].class.getName())).isEqualTo( success(int[][][][][].class)); } @Test void tryToLoadClassForMultidimensionalPrimitiveArrayUsingSourceCodeSyntax() { assertThat(ReflectionUtils.tryToLoadClass("int[][][][][]")).isEqualTo(success(int[][][][][].class)); } @Test void tryToLoadClassForMultidimensionalObjectArray() { assertThat(ReflectionUtils.tryToLoadClass(String[][][][][].class.getName())).isEqualTo( success(String[][][][][].class)); } @Test void tryToLoadClassForMultidimensionalObjectArrayUsingSourceCodeSyntax() { assertThat(ReflectionUtils.tryToLoadClass("java.lang.String[][][][][]")).isEqualTo( success(String[][][][][].class)); } @Test void getFullyQualifiedMethodNamePreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getFullyQualifiedMethodName(null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getFullyQualifiedMethodName(null, "testMethod")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getFullyQualifiedMethodName(Object.class, null)); // @formatter:on } @Test void getFullyQualifiedMethodNameForMethodWithoutParameters() { assertThat(ReflectionUtils.getFullyQualifiedMethodName(Object.class, "toString"))// .isEqualTo("java.lang.Object#toString()"); } @Test void getFullyQualifiedMethodNameForMethodWithNullParameters() { assertThat(ReflectionUtils.getFullyQualifiedMethodName(Object.class, "toString", (Class[]) null))// .isEqualTo("java.lang.Object#toString()"); } @Test void getFullyQualifiedMethodNameForMethodWithSingleParameter() { assertThat(ReflectionUtils.getFullyQualifiedMethodName(Object.class, "equals", Object.class))// .isEqualTo("java.lang.Object#equals(java.lang.Object)"); } @Test void getFullyQualifiedMethodNameForMethodWithMultipleParameters() { // @formatter:off assertThat(ReflectionUtils.getFullyQualifiedMethodName(Object.class, "testMethod", int.class, Object.class))// .isEqualTo("java.lang.Object#testMethod(int, java.lang.Object)"); // @formatter:on } @Test void parseFullyQualifiedMethodNamePreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName(null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName(" ")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("java.lang.Object#")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("#equals")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("#")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("java.lang.Object")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("equals")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("()")); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.parseFullyQualifiedMethodName("(int, java.lang.Object)")); // @formatter:on } @Test void parseFullyQualifiedMethodNameForMethodWithoutParameters() { assertThat(ReflectionUtils.parseFullyQualifiedMethodName("com.example.Test#method()"))// .containsExactly("com.example.Test", "method", ""); } @Test void parseFullyQualifiedMethodNameForMethodWithSingleParameter() { assertThat(ReflectionUtils.parseFullyQualifiedMethodName("com.example.Test#method(java.lang.Object)"))// .containsExactly("com.example.Test", "method", "java.lang.Object"); } @Test void parseFullyQualifiedMethodNameForMethodWithMultipleParameters() { assertThat(ReflectionUtils.parseFullyQualifiedMethodName("com.example.Test#method(int, java.lang.Object)"))// .containsExactly("com.example.Test", "method", "int, java.lang.Object"); } @Test @SuppressWarnings("deprecation") void getOutermostInstancePreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getOutermostInstance(null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getOutermostInstance(null, Object.class)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getOutermostInstance(new Object(), null)); // @formatter:on } @Test @SuppressWarnings("deprecation") void getOutermostInstance() { var firstClass = new FirstClass(); var secondClass = firstClass.new SecondClass(); var thirdClass = secondClass.new ThirdClass(); assertThat(ReflectionUtils.getOutermostInstance(thirdClass, FirstClass.SecondClass.ThirdClass.class))// .contains(thirdClass); assertThat(ReflectionUtils.getOutermostInstance(thirdClass, FirstClass.SecondClass.class))// .contains(secondClass); assertThat(ReflectionUtils.getOutermostInstance(thirdClass, FirstClass.class)).contains(firstClass); assertThat(ReflectionUtils.getOutermostInstance(thirdClass, String.class)).isEmpty(); } @Test void getAllClasspathRootDirectories(@TempDir Path tempDirectory) throws Exception { var root1 = tempDirectory.resolve("root1").toAbsolutePath(); var root2 = tempDirectory.resolve("root2").toAbsolutePath(); var testClassPath = root1 + File.pathSeparator + root2; var originalClassPath = System.setProperty("java.class.path", testClassPath); try { createDirectories(root1, root2); assertThat(ReflectionUtils.getAllClasspathRootDirectories()).containsOnly(root1, root2); } finally { System.setProperty("java.class.path", originalClassPath); } } @Test void findNestedClassesPreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.findNestedClasses(null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.findNestedClasses(null, clazz -> true)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.findNestedClasses(FirstClass.class, null)); // @formatter:on } @Test void findNestedClasses() { // @formatter:off assertThat(findNestedClasses(Object.class)).isEmpty(); assertThat(findNestedClasses(ClassWithNestedClasses.class)) .containsOnly(Nested1.class, Nested2.class, Nested3.class); assertThat(ReflectionUtils.findNestedClasses(ClassWithNestedClasses.class, clazz -> clazz.getName().contains("1"))) .containsExactly(Nested1.class); assertThat(ReflectionUtils.findNestedClasses(ClassWithNestedClasses.class, ReflectionUtils::isStatic)) .containsExactly(Nested3.class); assertThat(findNestedClasses(ClassExtendingClassWithNestedClasses.class)) .containsOnly(Nested1.class, Nested2.class, Nested3.class, Nested4.class, Nested5.class); assertThat(findNestedClasses(ClassWithNestedClasses.Nested1.class)).isEmpty(); // @formatter:on } /** * @since 1.6 */ @Test void findNestedClassesWithSeeminglyRecursiveHierarchies() { assertThat(findNestedClasses(AbstractOuterClass.class))// .containsExactly(AbstractOuterClass.InnerClass.class); // OuterClass contains recursive hierarchies, but the non-matching // predicate should prevent cycle detection. // See https://github.com/junit-team/junit5/issues/2249 assertThat(ReflectionUtils.findNestedClasses(OuterClass.class, clazz -> false)).isEmpty(); // RecursiveInnerInnerClass is part of a recursive hierarchy, but the non-matching // predicate should prevent cycle detection. assertThat(ReflectionUtils.findNestedClasses(RecursiveInnerInnerClass.class, clazz -> false)).isEmpty(); // Sibling types don't actually result in cycles. assertThat(findNestedClasses(StaticNestedSiblingClass.class))// .containsExactly(AbstractOuterClass.InnerClass.class); assertThat(findNestedClasses(InnerSiblingClass.class))// .containsExactly(AbstractOuterClass.InnerClass.class); // Interfaces with static nested classes assertThat(findNestedClasses(OuterClassImplementingInterface.class))// .containsExactly(InnerClassImplementingInterface.class, Nested4.class); assertThat(findNestedClasses(InnerClassImplementingInterface.class))// .containsExactly(Nested4.class); } /** * @since 1.6 */ @Test void findNestedClassesWithRecursiveHierarchies() { Runnable runnable1 = () -> assertNestedCycle(OuterClass.class, InnerClass.class, OuterClass.class); Runnable runnable2 = () -> assertNestedCycle(StaticNestedClass.class, InnerClass.class, OuterClass.class); Runnable runnable3 = () -> assertNestedCycle(RecursiveInnerClass.class, OuterClass.class); Runnable runnable4 = () -> assertNestedCycle(RecursiveInnerInnerClass.class, OuterClass.class); Runnable runnable5 = () -> assertNestedCycle(InnerClass.class, RecursiveInnerInnerClass.class, OuterClass.class); Stream.of(runnable1, runnable1, runnable1, runnable2, runnable2, runnable2, runnable3, runnable3, runnable3, runnable4, runnable4, runnable4, runnable5, runnable5, runnable5).parallel().forEach(Runnable::run); } private static List> findNestedClasses(Class clazz) { return ReflectionUtils.findNestedClasses(clazz, c -> true); } private void assertNestedCycle(Class from, Class to) { assertNestedCycle(from, from, to); } private void assertNestedCycle(Class start, Class from, Class to) { assertThatExceptionOfType(JUnitException.class)// .as("expected cycle from %s to %s", from.getSimpleName(), to.getSimpleName())// .isThrownBy(() -> findNestedClasses(start))// .withMessageMatching(String.format("Detected cycle in inner class hierarchy between .+%s and .+%s", from.getSimpleName(), to.getSimpleName())); } /** * @since 1.3 */ @Test @TrackLogRecords void findNestedClassesWithInvalidNestedClassFile(LogRecordListener listener) throws Exception { var jarUrl = getClass().getResource("/gh-1436-invalid-nested-class-file.jar"); try (var classLoader = new URLClassLoader(new URL[] { jarUrl })) { var fqcn = "tests.NestedInterfaceGroovyTests"; var classWithInvalidNestedClassFile = classLoader.loadClass(fqcn); assertEquals(fqcn, classWithInvalidNestedClassFile.getName()); var noClassDefFoundError = assertThrows(NoClassDefFoundError.class, classWithInvalidNestedClassFile::getDeclaredClasses); assertEquals("tests/NestedInterfaceGroovyTests$NestedInterface$1", noClassDefFoundError.getMessage()); assertThat(findNestedClasses(classWithInvalidNestedClassFile)).isEmpty(); // @formatter:off var logMessage = listener.stream(ReflectionUtils.class, Level.FINE) .findFirst() .map(LogRecord::getMessage) .orElse("didn't find log record"); // @formatter:on assertThat(logMessage).isEqualTo("Failed to retrieve declared classes for " + fqcn); } } @Test void getDeclaredConstructorPreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getDeclaredConstructor(null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.getDeclaredConstructor(ClassWithTwoConstructors.class)); // @formatter:on } @Test void getDeclaredConstructor() { Constructor constructor = ReflectionUtils.getDeclaredConstructor(getClass()); assertNotNull(constructor); assertEquals(getClass(), constructor.getDeclaringClass()); constructor = ReflectionUtils.getDeclaredConstructor(ClassWithOneCustomConstructor.class); assertNotNull(constructor); assertEquals(ClassWithOneCustomConstructor.class, constructor.getDeclaringClass()); assertEquals(String.class, constructor.getParameterTypes()[0]); } @Test void tryToGetMethodPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToGetMethod(null, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToGetMethod(String.class, null)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToGetMethod(null, "hashCode")); } @Test void tryToGetMethod() throws Exception { assertThat(ReflectionUtils.tryToGetMethod(Object.class, "hashCode").get()).isEqualTo( Object.class.getMethod("hashCode")); assertThat(ReflectionUtils.tryToGetMethod(String.class, "charAt", int.class).get())// .isEqualTo(String.class.getMethod("charAt", int.class)); assertThat(ReflectionUtils.tryToGetMethod(Path.class, "subpath", int.class, int.class).get())// .isEqualTo(Path.class.getMethod("subpath", int.class, int.class)); assertThat(ReflectionUtils.tryToGetMethod(String.class, "chars").get()).isEqualTo( String.class.getMethod("chars")); assertThat(ReflectionUtils.tryToGetMethod(String.class, "noSuchMethod").toOptional()).isEmpty(); assertThat(ReflectionUtils.tryToGetMethod(Object.class, "clone", int.class).toOptional()).isEmpty(); } @Test void isMethodPresentPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.isMethodPresent(null, m -> true)); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.isMethodPresent(getClass(), null)); } @Test void isMethodPresent() { Predicate isMethod1 = method -> (method.getName().equals("method1") && method.getParameterTypes().length == 1 && method.getParameterTypes()[0] == String.class); assertThat(ReflectionUtils.isMethodPresent(MethodShadowingChild.class, isMethod1)).isTrue(); assertThat(ReflectionUtils.isMethodPresent(getClass(), isMethod1)).isFalse(); } @Test void findMethodByParameterTypesPreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> findMethod(null, null)); assertThrows(PreconditionViolationException.class, () -> findMethod(null, "method")); RuntimeException exception = assertThrows(PreconditionViolationException.class, () -> findMethod(String.class, null)); assertThat(exception).hasMessage("Method name must not be null or blank"); exception = assertThrows(PreconditionViolationException.class, () -> findMethod(String.class, " ")); assertThat(exception).hasMessage("Method name must not be null or blank"); exception = assertThrows(PreconditionViolationException.class, () -> findMethod(Files.class, "copy", (Class[]) null)); assertThat(exception).hasMessage("Parameter types array must not be null"); exception = assertThrows(PreconditionViolationException.class, () -> findMethod(Files.class, "copy", (Class) null)); assertThat(exception).hasMessage("Individual parameter types must not be null"); exception = assertThrows(PreconditionViolationException.class, () -> findMethod(Files.class, "copy", new Class[] { Path.class, null })); assertThat(exception).hasMessage("Individual parameter types must not be null"); // @formatter:on } @Test void findMethodByParameterTypes() throws Exception { assertThat(findMethod(Object.class, "noSuchMethod")).isEmpty(); assertThat(findMethod(String.class, "noSuchMethod")).isEmpty(); assertThat(findMethod(String.class, "chars")).contains(String.class.getMethod("chars")); assertThat(findMethod(Files.class, "copy", Path.class, OutputStream.class))// .contains(Files.class.getMethod("copy", Path.class, OutputStream.class)); assertThat(findMethod(MethodShadowingChild.class, "method1", String.class))// .contains(MethodShadowingChild.class.getMethod("method1", String.class)); } @Test void findMethodByParameterTypesInGenericInterface() { Class ifc = InterfaceWithGenericDefaultMethod.class; var method = findMethod(ifc, "foo", Number.class); assertThat(method).isNotEmpty(); assertThat(method.get().getName()).isEqualTo("foo"); } /** * @see #findMethodByParameterTypesWithOverloadedMethodNextToGenericDefaultMethod() */ @Test void findMethodByParameterTypesInGenericInterfaceViaParameterizedSubclass() { Class clazz = InterfaceWithGenericDefaultMethodImpl.class; var method = findMethod(clazz, "foo", Long.class); assertThat(method).isNotEmpty(); assertThat(method.get().getName()).isEqualTo("foo"); // One might expect or desire that the signature for the generic foo(N) // default method would be "foo(java.lang.Long)" when looked up via the // concrete parameterized class, but it apparently is only _visible_ as // "foo(java.lang.Number)" via reflection. Hence the following assertion // checks for java.lang.Number instead of java.lang.Long. assertThat(method.get().getParameterTypes()[0]).isEqualTo(Number.class); } /** * This test is identical to * {@link #findMethodByParameterTypesInGenericInterfaceViaParameterizedSubclass()}, * except that this test attempts to find the overloaded * {@link InterfaceWithGenericDefaultMethodImpl#foo(Double)} method instead of * the {@link InterfaceWithGenericDefaultMethod#foo(Number)} default method. */ @Test void findMethodByParameterTypesWithOverloadedMethodNextToGenericDefaultMethod() { Class clazz = InterfaceWithGenericDefaultMethodImpl.class; Class parameterType = Double.class; var method = findMethod(clazz, "foo", parameterType); assertThat(method).isNotEmpty(); assertThat(method.get().getName()).isEqualTo("foo"); assertThat(method.get().getParameterTypes()[0]).isEqualTo(parameterType); } @Test void findMethodByParameterNamesWithPrimitiveArrayParameter() throws Exception { assertFindMethodByParameterNames("methodWithPrimitiveArray", int[].class); } @Test void findMethodByParameterNamesWithTwoDimensionalPrimitiveArrayParameter() throws Exception { assertFindMethodByParameterNames("methodWithTwoDimensionalPrimitiveArray", int[][].class); } @Test void findMethodByParameterNamesWithMultidimensionalPrimitiveArrayParameter() throws Exception { assertFindMethodByParameterNames("methodWithMultidimensionalPrimitiveArray", int[][][][][].class); } @Test void findMethodByParameterNamesWithObjectArrayParameter() throws Exception { assertFindMethodByParameterNames("methodWithObjectArray", String[].class); } @Test void findMethodByParameterNamesWithMultidimensionalObjectArrayParameter() throws Exception { assertFindMethodByParameterNames("methodWithMultidimensionalObjectArray", Double[][][][][].class); } /** * @since 5.10 */ @Test void findMethodByParameterNamesWithWithCustomTypeFromDifferentClassLoader() throws Exception { var methodName = "customMethod"; var customTypeName = CustomType.class.getName(); var nestedTypeName = CustomType.NestedType.class.getName(); try (var testClassLoader = TestClassLoader.forClassNamePrefix(customTypeName)) { var customType = testClassLoader.loadClass(customTypeName); assertThat(customType.getClassLoader()).isSameAs(testClassLoader); var optional = findMethod(customType, methodName, nestedTypeName); assertThat(optional).get().satisfies(method -> { assertThat(method.getName()).isEqualTo(methodName); var declaringClass = method.getDeclaringClass(); assertThat(declaringClass.getClassLoader()).isSameAs(testClassLoader); assertThat(declaringClass.getName()).isEqualTo(customTypeName); assertThat(declaringClass).isNotEqualTo(CustomType.class); var parameterTypes = method.getParameterTypes(); assertThat(parameterTypes).extracting(Class::getName).containsExactly(nestedTypeName); Class parameterType = parameterTypes[0]; assertThat(parameterType).isNotEqualTo(CustomType.NestedType.class); assertThat(parameterType.getClassLoader()).isSameAs(testClassLoader); }); } } @Test void findMethodByParameterNamesWithParameterizedMapParameter() throws Exception { var methodName = "methodWithParameterizedMap"; // standard, supported use case assertFindMethodByParameterNames(methodName, Map.class); // generic type info in parameter list var method = getClass().getDeclaredMethod(methodName, Map.class); var genericParameterTypeName = method.getGenericParameterTypes()[0].getTypeName(); var exception = assertThrows(JUnitException.class, () -> findMethod(getClass(), methodName, genericParameterTypeName)); assertThat(exception).hasMessageStartingWith("Failed to load parameter type [java.util.Map parameterType) throws NoSuchMethodException { var method = getClass().getDeclaredMethod(methodName, parameterType); var optional = findMethod(getClass(), methodName, parameterType.getName()); assertThat(optional).contains(method); } @Test void findMethodsPreconditions() { // @formatter:off assertThrows(PreconditionViolationException.class, () -> findMethods(null, null)); assertThrows(PreconditionViolationException.class, () -> findMethods(null, clazz -> true)); assertThrows(PreconditionViolationException.class, () -> findMethods(String.class, null)); assertThrows(PreconditionViolationException.class, () -> findMethods(null, null, null)); assertThrows(PreconditionViolationException.class, () -> findMethods(null, clazz -> true, BOTTOM_UP)); assertThrows(PreconditionViolationException.class, () -> findMethods(String.class, null, BOTTOM_UP)); assertThrows(PreconditionViolationException.class, () -> findMethods(String.class, clazz -> true, null)); // @formatter:on } @Test void findMethodsInInterface() { assertOneFooMethodIn(InterfaceWithOneDeclaredMethod.class); assertOneFooMethodIn(InterfaceWithDefaultMethod.class); assertOneFooMethodIn(InterfaceWithDefaultMethodImpl.class); assertOneFooMethodIn(InterfaceWithStaticMethod.class); assertOneFooMethodIn(InterfaceWithStaticMethodImpl.class); } private static void assertOneFooMethodIn(Class clazz) { assertThat(findMethods(clazz, isFooMethod)).hasSize(1); } /** * @since 1.9.1 * @see https://github.com/junit-team/junit5/issues/2993 */ @Test void findMethodsFindsDistinctMethodsDeclaredInMultipleInterfaces() { Predicate isStringsMethod = method -> method.getName().equals("strings"); assertThat(findMethods(DoubleInheritedInterfaceMethodTestCase.class, isStringsMethod)).hasSize(1); } @Test void findMethodsInObject() { var methods = findMethods(Object.class, method -> true); assertNotNull(methods); assertTrue(methods.size() > 10); } @Test void findMethodsInVoid() { assertThat(findMethods(void.class, method -> true)).isEmpty(); assertThat(findMethods(Void.class, method -> true)).isEmpty(); } @Test void findMethodsInPrimitive() { assertThat(findMethods(int.class, method -> true)).isEmpty(); } @Test void findMethodsInArrays() { assertThat(findMethods(int[].class, method -> true)).isEmpty(); assertThat(findMethods(Integer[].class, method -> true)).isEmpty(); } @Test void findMethodsIgnoresSyntheticMethods() { assertTrue(stream(ClassWithSyntheticMethod.class.getDeclaredMethods()).anyMatch(Method::isSynthetic), "ClassWithSyntheticMethod must actually contain at least one synthetic method."); var methods = findMethods(ClassWithSyntheticMethod.class, method -> true); assertThat(methods).isEmpty(); } @Test void findMethodsUsingHierarchyUpMode() throws Exception { assertThat(findMethods(ChildClass.class, method -> method.getName().contains("method"), BOTTOM_UP))// .containsExactly(ChildClass.class.getMethod("method4"), ParentClass.class.getMethod("method3"), GrandparentInterface.class.getMethod("method2"), GrandparentClass.class.getMethod("method1")); assertThat(findMethods(ChildClass.class, method -> method.getName().contains("other"), BOTTOM_UP))// .containsExactly(ChildClass.class.getMethod("otherMethod3"), ParentClass.class.getMethod("otherMethod2"), GrandparentClass.class.getMethod("otherMethod1")); assertThat(findMethods(ChildClass.class, method -> method.getName().equals("method2"), BOTTOM_UP))// .containsExactly(ParentClass.class.getMethod("method2")); assertThat(findMethods(ChildClass.class, method -> method.getName().equals("wrongName"), BOTTOM_UP)).isEmpty(); assertThat(findMethods(ParentClass.class, method -> method.getName().contains("method"), BOTTOM_UP))// .containsExactly(ParentClass.class.getMethod("method3"), GrandparentInterface.class.getMethod("method2"), GrandparentClass.class.getMethod("method1")); } @Test void findMethodsUsingHierarchyDownMode() throws Exception { assertThat(findMethods(ChildClass.class, method -> method.getName().contains("method"), TOP_DOWN))// .containsExactly(GrandparentClass.class.getMethod("method1"), GrandparentInterface.class.getMethod("method2"), ParentClass.class.getMethod("method3"), ChildClass.class.getMethod("method4")); assertThat(findMethods(ChildClass.class, method -> method.getName().contains("other"), TOP_DOWN))// .containsExactly(GrandparentClass.class.getMethod("otherMethod1"), ParentClass.class.getMethod("otherMethod2"), ChildClass.class.getMethod("otherMethod3")); assertThat(findMethods(ChildClass.class, method -> method.getName().equals("method2"), TOP_DOWN))// .containsExactly(ParentClass.class.getMethod("method2")); assertThat(findMethods(ChildClass.class, method -> method.getName().equals("wrongName"), TOP_DOWN)).isEmpty(); assertThat(findMethods(ParentClass.class, method -> method.getName().contains("method"), TOP_DOWN))// .containsExactly(GrandparentClass.class.getMethod("method1"), GrandparentInterface.class.getMethod("method2"), ParentClass.class.getMethod("method3")); } @Test void findMethodsWithShadowingUsingHierarchyUpMode() throws Exception { assertThat(findMethods(MethodShadowingChild.class, methodContains1, BOTTOM_UP))// .containsExactly(MethodShadowingChild.class.getMethod("method1", String.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains2, BOTTOM_UP))// .containsExactly(MethodShadowingParent.class.getMethod("method2", int.class, int.class, int.class), MethodShadowingInterface.class.getMethod("method2", int.class, int.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains4, BOTTOM_UP))// .containsExactly(MethodShadowingChild.class.getMethod("method4", boolean.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains5, BOTTOM_UP))// .containsExactly(MethodShadowingChild.class.getMethod("method5", Long.class), MethodShadowingParent.class.getMethod("method5", String.class)); var methods = findMethods(MethodShadowingChild.class, method -> true, BOTTOM_UP); assertEquals(6, methods.size()); assertThat(methods.subList(0, 3)).containsOnly(MethodShadowingChild.class.getMethod("method4", boolean.class), MethodShadowingChild.class.getMethod("method1", String.class), MethodShadowingChild.class.getMethod("method5", Long.class)); assertThat(methods.subList(3, 5)).containsOnly( MethodShadowingParent.class.getMethod("method2", int.class, int.class, int.class), MethodShadowingParent.class.getMethod("method5", String.class)); assertEquals(MethodShadowingInterface.class.getMethod("method2", int.class, int.class), methods.get(5)); } @Test void findMethodsWithShadowingUsingHierarchyDownMode() throws Exception { assertThat(findMethods(MethodShadowingChild.class, methodContains1, TOP_DOWN))// .containsExactly(MethodShadowingChild.class.getMethod("method1", String.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains2, TOP_DOWN))// .containsExactly(MethodShadowingInterface.class.getMethod("method2", int.class, int.class), MethodShadowingParent.class.getMethod("method2", int.class, int.class, int.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains4, TOP_DOWN))// .containsExactly(MethodShadowingChild.class.getMethod("method4", boolean.class)); assertThat(findMethods(MethodShadowingChild.class, methodContains5, TOP_DOWN))// .containsExactly(MethodShadowingParent.class.getMethod("method5", String.class), MethodShadowingChild.class.getMethod("method5", Long.class)); var methods = findMethods(MethodShadowingChild.class, method -> true, TOP_DOWN); assertEquals(6, methods.size()); assertEquals(MethodShadowingInterface.class.getMethod("method2", int.class, int.class), methods.get(0)); assertThat(methods.subList(1, 3)).containsOnly( MethodShadowingParent.class.getMethod("method2", int.class, int.class, int.class), MethodShadowingParent.class.getMethod("method5", String.class)); assertThat(methods.subList(3, 6)).containsOnly(MethodShadowingChild.class.getMethod("method4", boolean.class), MethodShadowingChild.class.getMethod("method1", String.class), MethodShadowingChild.class.getMethod("method5", Long.class)); } @Test void findMethodsWithStaticHidingUsingHierarchyUpMode() throws Exception { Class ifc = StaticMethodHidingInterface.class; Class parent = StaticMethodHidingParent.class; Class child = StaticMethodHidingChild.class; var ifcMethod2 = ifc.getDeclaredMethod("method2", int.class, int.class); var childMethod1 = child.getDeclaredMethod("method1", String.class); var childMethod4 = child.getDeclaredMethod("method4", boolean.class); var childMethod5 = child.getDeclaredMethod("method5", Long.class); var parentMethod2 = parent.getDeclaredMethod("method2", int.class, int.class, int.class); var parentMethod5 = parent.getDeclaredMethod("method5", String.class); assertThat(findMethods(child, methodContains1, BOTTOM_UP)).containsExactly(childMethod1); assertThat(findMethods(child, methodContains2, BOTTOM_UP)).containsExactly(parentMethod2, ifcMethod2); assertThat(findMethods(child, methodContains4, BOTTOM_UP)).containsExactly(childMethod4); assertThat(findMethods(child, methodContains5, BOTTOM_UP)).containsExactly(childMethod5, parentMethod5); var methods = findMethods(child, method -> true, BOTTOM_UP); assertEquals(6, methods.size()); assertThat(methods.subList(0, 3)).containsOnly(childMethod1, childMethod4, childMethod5); assertThat(methods.subList(3, 5)).containsOnly(parentMethod2, parentMethod5); assertEquals(ifcMethod2, methods.get(5)); } @Test void findMethodsWithStaticHidingUsingHierarchyDownMode() throws Exception { Class ifc = StaticMethodHidingInterface.class; Class parent = StaticMethodHidingParent.class; Class child = StaticMethodHidingChild.class; var ifcMethod2 = ifc.getDeclaredMethod("method2", int.class, int.class); var childMethod1 = child.getDeclaredMethod("method1", String.class); var childMethod4 = child.getDeclaredMethod("method4", boolean.class); var childMethod5 = child.getDeclaredMethod("method5", Long.class); var parentMethod2 = parent.getDeclaredMethod("method2", int.class, int.class, int.class); var parentMethod5 = parent.getDeclaredMethod("method5", String.class); assertThat(findMethods(child, methodContains1, TOP_DOWN)).containsExactly(childMethod1); assertThat(findMethods(child, methodContains2, TOP_DOWN)).containsExactly(ifcMethod2, parentMethod2); assertThat(findMethods(child, methodContains4, TOP_DOWN)).containsExactly(childMethod4); assertThat(findMethods(child, methodContains5, TOP_DOWN)).containsExactly(parentMethod5, childMethod5); var methods = findMethods(child, method -> true, TOP_DOWN); assertEquals(6, methods.size()); assertEquals(ifcMethod2, methods.get(0)); assertThat(methods.subList(1, 3)).containsOnly(parentMethod2, parentMethod5); assertThat(methods.subList(3, 6)).containsOnly(childMethod1, childMethod4, childMethod5); } @Test void findMethodsReturnsAllOverloadedMethodsThatAreNotShadowed() { Class clazz = InterfaceWithGenericDefaultMethodImpl.class; // Search for all foo(*) methods. var methods = findMethods(clazz, isFooMethod); // One might expect or desire that the signature for the generic foo(N) // default method would be "foo(java.lang.Long)" when looked up via the // concrete parameterized class, but it apparently is only _visible_ as // "foo(java.lang.Number)" via reflection. assertThat(signaturesOf(methods)).containsExactly("foo(java.lang.Number)", "foo(java.lang.Double)"); } @Test void findMethodsDoesNotReturnOverriddenDefaultMethods() { Class clazz = InterfaceWithOverriddenGenericDefaultMethodImpl.class; // Search for all foo(*) methods. var methods = findMethods(clazz, isFooMethod); var signatures = signaturesOf(methods); // Although the subsequent assertion covers this case as well, this // assertion is in place to provide a more informative failure message. assertThat(signatures).as("overridden default method should not be in results").doesNotContain( "foo(java.lang.Number)"); assertThat(signatures).containsExactly("foo(java.lang.Long)", "foo(java.lang.Double)"); } private static List signaturesOf(List methods) { // @formatter:off return methods.stream() .map(m -> String.format("%s(%s)", m.getName(), ClassUtils.nullSafeToString(m.getParameterTypes()))) .collect(toList()); // @formatter:on } @Test void findMethodsIgnoresBridgeMethods() throws Exception { assertFalse(Modifier.isPublic(PublicChildClass.class.getSuperclass().getModifiers())); assertTrue(Modifier.isPublic(PublicChildClass.class.getModifiers())); assertTrue(PublicChildClass.class.getDeclaredMethod("method1").isBridge()); assertTrue(PublicChildClass.class.getDeclaredMethod("method3").isBridge()); var methods = findMethods(PublicChildClass.class, method -> true); var signatures = signaturesOf(methods); assertThat(signatures).containsOnly("method1()", "method2()", "method3()", "otherMethod1()", "otherMethod2()"); assertEquals(0, methods.stream().filter(Method::isBridge).count()); } /** * @see https://github.com/junit-team/junit5/issues/3553 */ @Disabled("Until #3553 is resolved") @Test void findMethodsDoesNotAllowInstanceMethodToHideStaticMethod() throws Exception { final String BEFORE = "before"; Class superclass = SuperclassWithStaticPackagePrivateBeforeMethod.class; Method staticMethod = superclass.getDeclaredMethod(BEFORE); Class subclass = SubclassWithNonStaticPackagePrivateBeforeMethod.class; Method nonStaticMethod = subclass.getDeclaredMethod(BEFORE); // Prerequisite var methods = findMethods(superclass, ReflectionUtils::isStatic); assertThat(methods).containsExactly(staticMethod); // Actual use cases for this test methods = findMethods(subclass, ReflectionUtils::isStatic); assertThat(methods).containsExactly(staticMethod); methods = findMethods(subclass, ReflectionUtils::isNotStatic); assertThat(methods).containsExactly(nonStaticMethod); } @Test void isGeneric() { for (var method : Generic.class.getMethods()) { assertTrue(ReflectionUtils.isGeneric(method)); } for (var method : PublicClass.class.getMethods()) { assertFalse(ReflectionUtils.isGeneric(method)); } } /** * @see https://github.com/junit-team/junit5/issues/3553 */ @Disabled("Until #3553 is resolved") @Test void findFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exception { final String TEMP_DIR = "tempDir"; Class superclass = SuperclassWithStaticPackagePrivateTempDirField.class; Field staticField = superclass.getDeclaredField(TEMP_DIR); Class subclass = SubclassWithNonStaticPackagePrivateTempDirField.class; Field nonStaticField = subclass.getDeclaredField(TEMP_DIR); // Prerequisite var fields = findFields(superclass, ReflectionUtils::isStatic, TOP_DOWN); assertThat(fields).containsExactly(staticField); // Actual use cases for this test fields = findFields(subclass, ReflectionUtils::isStatic, TOP_DOWN); assertThat(fields).containsExactly(staticField); fields = findFields(subclass, ReflectionUtils::isNotStatic, TOP_DOWN); assertThat(fields).containsExactly(nonStaticField); } @Test void readFieldValuesPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.readFieldValues(null, new Object())); assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.readFieldValues(new ArrayList<>(), new Object(), null)); } @Test void readFieldValuesFromInstance() { var fields = findFields(ClassWithFields.class, f -> true, TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, new ClassWithFields()); assertThat(values).containsExactly("enigma", 3.14, "text", 2.5, null, 42, "constant", 99); } @Test void readFieldValuesFromClass() { var fields = findFields(ClassWithFields.class, ReflectionUtils::isStatic, TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, null); assertThat(values).containsExactly(2.5, "constant", 99); } @Test void readFieldValuesFromInstanceWithTypeFilterForString() { var fields = findFields(ClassWithFields.class, isA(String.class), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, new ClassWithFields(), isA(String.class)); assertThat(values).containsExactly("enigma", "text", null, "constant"); } @Test void readFieldValuesFromClassWithTypeFilterForString() { var fields = findFields(ClassWithFields.class, isA(String.class).and(ReflectionUtils::isStatic), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, null, isA(String.class)); assertThat(values).containsExactly("constant"); } @Test void readFieldValuesFromInstanceWithTypeFilterForInteger() { var fields = findFields(ClassWithFields.class, isA(int.class), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, new ClassWithFields(), isA(int.class)); assertThat(values).containsExactly(42); } @Test void readFieldValuesFromClassWithTypeFilterForInteger() { var fields = findFields(ClassWithFields.class, isA(Integer.class).and(ReflectionUtils::isStatic), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, null, isA(Integer.class)); assertThat(values).containsExactly(99); } @Test void readFieldValuesFromInstanceWithTypeFilterForDouble() { var fields = findFields(ClassWithFields.class, isA(double.class), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, new ClassWithFields(), isA(double.class)); assertThat(values).containsExactly(3.14); } @Test void readFieldValuesFromClassWithTypeFilterForDouble() { var fields = findFields(ClassWithFields.class, isA(Double.class).and(ReflectionUtils::isStatic), TOP_DOWN); var values = ReflectionUtils.readFieldValues(fields, null, isA(Double.class)); assertThat(values).containsExactly(2.5); } private Predicate isA(Class type) { return f -> f.getType().isAssignableFrom(type); } private static void createDirectories(Path... paths) throws IOException { for (var path : paths) { Files.createDirectory(path); } } // ------------------------------------------------------------------------- void methodWithPrimitiveArray(int[] nums) { } void methodWithTwoDimensionalPrimitiveArray(int[][] grid) { } void methodWithMultidimensionalPrimitiveArray(int[][][][][] grid) { } void methodWithObjectArray(String[] info) { } void methodWithTwoDimensionalObjectArray(String[][] info) { } void methodWithMultidimensionalObjectArray(Double[][][][][] data) { } void methodWithParameterizedMap(Map map) { } interface StringsInterface1 { static Stream strings() { return Stream.of("abc", "def"); } } interface StringsInterface2 extends StringsInterface1 { } /** * Inherits strings() from interfaces StringsInterface1 and StringsInterface2. */ static class DoubleInheritedInterfaceMethodTestCase implements StringsInterface1, StringsInterface2 { } interface Generic { X foo(); Y foo(X x, Y y); Z foo(Z[][] zees); int foo(T t); T foo(int i); } class ClassWithSyntheticMethod { // The following lambda expression results in a synthetic method in the // compiled byte code. Comparable synthetic = number -> 0; } interface InterfaceWithOneDeclaredMethod { void foo(); } interface InterfaceWithDefaultMethod { default void foo() { } } static class InterfaceWithDefaultMethodImpl implements InterfaceWithDefaultMethod { } interface InterfaceWithGenericDefaultMethod { default void foo(N number) { } } static class InterfaceWithGenericDefaultMethodImpl implements InterfaceWithGenericDefaultMethod { void foo(Double number) { } } static class InterfaceWithOverriddenGenericDefaultMethodImpl implements InterfaceWithGenericDefaultMethod { @Override public void foo(Long number) { } void foo(Double number) { } } interface InterfaceWithStaticMethod { static void foo() { } } static class InterfaceWithStaticMethodImpl implements InterfaceWithStaticMethod { } interface InterfaceA { } interface InterfaceB { } interface InterfaceC extends InterfaceA, InterfaceB { } interface InterfaceD { } static class A implements InterfaceA, InterfaceD { } static class B extends A implements InterfaceC { } static class C { C() { } C(String a, String b) { } } static class Exploder { Exploder() { throw new RuntimeException("boom"); } } static class MyClass { static final int staticField = 42; final int instanceField; MyClass(int value) { this.instanceField = value; } } static class MySubClass extends MyClass { MySubClass(int value) { super(value); } } // Intentionally non-static public class PublicClass { public void publicMethod() { } public void method(String str, Integer num) { } public void method(String[] strings, Integer[] nums) { } public void method(boolean b, char c) { } public void method(char[] characters, int[] nums) { } } private class PrivateClass { @SuppressWarnings("unused") private void privateMethod() { } } protected class ProtectedClass { @SuppressWarnings("unused") protected void protectedMethod() { } } class PackageVisibleClass { @SuppressWarnings("unused") void packageVisibleMethod() { } } final class FinalClass { @SuppressWarnings("unused") final void finalMethod() { } } abstract static class AbstractClass { abstract void abstractMethod(); } static class StaticClass { static void staticMethod() { } } static class ClassWithVoidAndNonVoidMethods { void voidMethod() { } Void methodReturningVoidReference() { return null; } String methodReturningObject() { return ""; } int methodReturningPrimitive() { return 0; } } static class InvocationTracker { static boolean publicStaticMethodInvoked; static boolean privateStaticMethodInvoked; boolean publicMethodInvoked; boolean privateMethodInvoked; public static void publicStaticMethod() { publicStaticMethodInvoked = true; } @SuppressWarnings("unused") private static void privateStaticMethod() { privateStaticMethodInvoked = true; } public void publicMethod() { publicMethodInvoked = true; } @SuppressWarnings("unused") private void privateMethod() { privateMethodInvoked = true; } } static class FirstClass { class SecondClass { class ThirdClass { } } } static class ClassWithNestedClasses { class Nested1 { } class Nested2 { } static class Nested3 { } } interface InterfaceWithNestedClass { class Nested4 { } } interface Interface45 extends InterfaceWithNestedClass { class Nested5 { } } static class ClassExtendingClassWithNestedClasses extends ClassWithNestedClasses implements Interface45 { } abstract static class AbstractOuterClass { class InnerClass { } } static class OuterClass extends AbstractOuterClass { // sibling of OuterClass due to common super type static class StaticNestedSiblingClass extends AbstractOuterClass { } // sibling of OuterClass due to common super type class InnerSiblingClass extends AbstractOuterClass { } static class StaticNestedClass extends OuterClass { } class RecursiveInnerClass extends OuterClass { } class InnerClass { class RecursiveInnerInnerClass extends OuterClass { } } } static class OuterClassImplementingInterface implements InterfaceWithNestedClass { class InnerClassImplementingInterface implements InterfaceWithNestedClass { } } static class GrandparentClass { public void method1() { } public void otherMethod1() { } } interface GrandparentInterface { default void method2() { } } static class ParentClass extends GrandparentClass implements GrandparentInterface { public void method3() { } public void otherMethod2() { } } static class ChildClass extends ParentClass { public void method4() { } public void otherMethod3() { } } interface MethodShadowingInterface { default void method1(String string) { } default void method2(int i, int j) { } } static class MethodShadowingParent implements MethodShadowingInterface { @Override public void method1(String string) { } public void method2(int i, int j, int k) { } public void method4(boolean flag) { } public void method5(String string) { } } static class MethodShadowingChild extends MethodShadowingParent { @Override public void method1(String string) { } @Override public void method4(boolean flag) { } public void method5(Long i) { } } interface StaticMethodHidingInterface { static void method1(String string) { } static void method2(int i, int j) { } } static class StaticMethodHidingParent implements StaticMethodHidingInterface { static void method1(String string) { } static void method2(int i, int j, int k) { } static void method4(boolean flag) { } static void method5(String string) { } } static class StaticMethodHidingChild extends StaticMethodHidingParent { static void method1(String string) { } static void method4(boolean flag) { } static void method5(Long i) { } } // "public" modifier is necessary here, so that the compiler creates a bridge method. public static class PublicChildClass extends ParentClass { @Override public void otherMethod1() { } @Override public void otherMethod2() { } } public static class ClassWithFields { public static final String CONST = "constant"; public static final Integer CONST_INTEGER = 99; public static final Double CONST_DOUBLE = 2.5; public final String stringField = "text"; @SuppressWarnings("unused") private final String privateStringField = "enigma"; final String nullStringField = null; public final int integerField = 42; public final double doubleField = 3.14; } @SuppressWarnings("unused") private static class ClassWithOneCustomConstructor { ClassWithOneCustomConstructor(String str) { } } @SuppressWarnings("unused") private static class ClassWithTwoConstructors { ClassWithTwoConstructors() { } ClassWithTwoConstructors(String str) { } } } ReflectionUtilsWithGenericTypeHierarchiesTests.java000066400000000000000000000135731455764576500411730ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.platform.commons.util.ReflectionUtils.findMethod; import java.lang.reflect.Method; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @SuppressWarnings("TypeParameterExplicitlyExtendsObject") class ReflectionUtilsWithGenericTypeHierarchiesTests { @Test @Disabled("Describes a new case that does not yet yield the expected result.") void findsMethodsIndependentlyFromOrderOfImplementationsOfInterfaces() { class AB implements InterfaceDouble, InterfaceGenericNumber { } class BA implements InterfaceGenericNumber, InterfaceDouble { } var methodAB = findMethod(AB.class, "foo", Double.class).orElseThrow(); var methodBA = findMethod(BA.class, "foo", Double.class).orElseThrow(); assertEquals(methodAB, methodBA); } @Test void findMoreSpecificMethodFromAbstractImplementationOverDefaultInterfaceMethod() { class A implements InterfaceGenericNumber { @Override public void foo(Long parameter) { } } var foo = findMethod(A.class, "foo", Long.class).orElseThrow(); assertEquals(A.class, foo.getDeclaringClass()); } @Test @Disabled("Describes a new case that does not yet yield the expected result.") void findMoreSpecificMethodFromOverriddenImplementationOfGenericInterfaceMethod() { class A implements InterfaceGenericNumber { @Override public void foo(Number parameter) { } } var foo = findMethod(A.class, "foo", Long.class).orElseThrow(); assertEquals(A.class, foo.getDeclaringClass()); } @Test @Disabled("Describes a new case that does not yet yield the expected result.") void findMoreSpecificMethodFromImplementationOverDefaultInterfaceMethodAndGenericClassExtension() { class AParent { @SuppressWarnings("unused") public void foo(Number parameter) { } } class A extends AParent implements InterfaceGenericNumber { @Override public void foo(Number parameter) { } } var foo = findMethod(A.class, "foo", Long.class).orElseThrow(); assertEquals(A.class, foo.getDeclaringClass()); } @Test @Disabled("Expected behaviour is not clear yet.") void unclearPrecedenceOfImplementationsInParentClassAndInterfaceDefault() { class AParent { public void foo(@SuppressWarnings("unused") Number parameter) { } } class A extends AParent implements InterfaceGenericNumber { } var foo = findMethod(A.class, "foo", Long.class).orElseThrow(); // ???????? assertEquals(A.class, foo.getDeclaringClass()); assertEquals(AParent.class, foo.getDeclaringClass()); assertEquals(InterfaceGenericNumber.class, foo.getDeclaringClass()); } @Test @Disabled("Describes cases where current implementation returns unexpected value") public void findMethodWithMostSpecificParameterTypeInHierarchy() { // Searched Parameter Type is more specific assertSpecificFooMethodFound(ClassImplementingInterfaceWithInvertedHierarchy.class, InterfaceWithGenericNumberParameter.class, Double.class); assertSpecificFooMethodFound(ClassImplementingGenericInterfaceWithMoreSpecificMethod.class, ClassImplementingGenericInterfaceWithMoreSpecificMethod.class, Double.class); assertSpecificFooMethodFound(ClassImplementingGenericAndMoreSpecificInterface.class, InterfaceWithGenericNumberParameter.class, Double.class); assertSpecificFooMethodFound(ClassOverridingDefaultMethodAndImplementingMoreSpecificInterface.class, ClassOverridingDefaultMethodAndImplementingMoreSpecificInterface.class, Double.class); // Exact Type Match assertSpecificFooMethodFound(ClassImplementingGenericInterfaceWithMoreSpecificMethod.class, ClassImplementingGenericInterfaceWithMoreSpecificMethod.class, Number.class); } private void assertSpecificFooMethodFound(Class classToSearchIn, Class classWithMostSpecificMethod, Class parameterType) { var foo = findMethod(classToSearchIn, "foo", parameterType).orElseThrow(); assertDeclaringClass(foo, classWithMostSpecificMethod); } private void assertDeclaringClass(Method method, Class expectedClass) { assertEquals(expectedClass, method.getDeclaringClass()); } interface InterfaceDouble { default void foo(@SuppressWarnings("unused") Double parameter) { } } interface InterfaceGenericNumber { default void foo(@SuppressWarnings("unused") T parameter) { } } public interface InterfaceWithGenericObjectParameter { default void foo(@SuppressWarnings("unused") T a) { } } public interface InterfaceWithGenericNumberParameter { default void foo(@SuppressWarnings("unused") T a) { } } public interface InterfaceExtendingNumberInterfaceWithGenericObjectMethod extends InterfaceWithGenericNumberParameter { default void foo(@SuppressWarnings("unused") T a) { } } public static class ClassImplementingGenericInterfaceWithMoreSpecificMethod implements InterfaceWithGenericObjectParameter { public void foo(@SuppressWarnings("unused") Number a) { } } public static class ClassImplementingGenericAndMoreSpecificInterface implements InterfaceWithGenericObjectParameter, InterfaceWithGenericNumberParameter { } public static class ClassOverridingDefaultMethodAndImplementingMoreSpecificInterface implements InterfaceWithGenericObjectParameter, InterfaceWithGenericNumberParameter { @Override public void foo(@SuppressWarnings("unused") T a) { } } public static class ClassImplementingInterfaceWithInvertedHierarchy implements InterfaceExtendingNumberInterfaceWithGenericObjectMethod { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/RuntimeUtilsTests.java000066400000000000000000000016041455764576500334310ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Unit tests for {@link RuntimeUtils}. * * @since 1.6 */ class RuntimeUtilsTests { @Test void jmxIsAvailableAndInputArgumentsAreReturned() { var optionalArguments = RuntimeUtils.getInputArguments(); assertTrue(optionalArguments.isPresent(), "JMX not available or something else happened..."); var arguments = optionalArguments.get(); assertNotNull(arguments); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/SerializationUtils.java000066400000000000000000000020331455764576500335750ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializationUtils { public static Object deserialize(byte[] bytes) throws Exception { try (var in = new ObjectInputStream(new ByteArrayInputStream(bytes))) { return in.readObject(); } } public static byte[] serialize(Object object) throws Exception { try (var byteArrayOutputStream = new ByteArrayOutputStream(); var objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { objectOutputStream.writeObject(object); objectOutputStream.flush(); return byteArrayOutputStream.toByteArray(); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java000066400000000000000000000167101455764576500332600ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.StringUtils.containsIsoControlCharacter; import static org.junit.platform.commons.util.StringUtils.containsWhitespace; import static org.junit.platform.commons.util.StringUtils.doesNotContainIsoControlCharacter; import static org.junit.platform.commons.util.StringUtils.doesNotContainWhitespace; import static org.junit.platform.commons.util.StringUtils.isBlank; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import static org.junit.platform.commons.util.StringUtils.nullSafeToString; import static org.junit.platform.commons.util.StringUtils.replaceIsoControlCharacters; import static org.junit.platform.commons.util.StringUtils.replaceWhitespaceCharacters; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link StringUtils}. * * @since 1.0 */ class StringUtilsTests { @Test void blankness() { // @formatter:off assertAll("Blankness", () -> assertTrue(isBlank(null)), () -> assertTrue(isBlank("")), () -> assertTrue(isBlank(" \t\n\r")), () -> assertTrue(isNotBlank(".")) ); // @formatter:on } @Test void whitespace() { // @formatter:off assertAll("Whitespace", () -> shouldContainWhitespace(" "), () -> shouldContainWhitespace("\u005Ct"), // horizontal tab () -> shouldContainWhitespace("\t"), () -> shouldContainWhitespace("\u005Cn"), // line feed () -> shouldContainWhitespace("\n"), () -> shouldContainWhitespace("\u005Cf"), // form feed () -> shouldContainWhitespace("\f"), () -> shouldContainWhitespace("\u005Cr"), // carriage return () -> shouldContainWhitespace("\r"), () -> shouldContainWhitespace("hello world"), () -> shouldNotContainWhitespace(null), () -> shouldNotContainWhitespace(""), () -> shouldNotContainWhitespace("hello-world"), () -> shouldNotContainWhitespace("0123456789"), () -> shouldNotContainWhitespace("$-_=+!@.,") ); // @formatter:on } @Test void controlCharacters() { // @formatter:off assertAll("ISO Control Characters", () -> shouldContainIsoControlCharacter("\u005Ct"), // horizontal tab () -> shouldContainIsoControlCharacter("\t"), () -> shouldContainIsoControlCharacter("\u005Cn"), // line feed () -> shouldContainIsoControlCharacter("\n"), () -> shouldContainIsoControlCharacter("\u005Cf"), // form feed () -> shouldContainIsoControlCharacter("\f"), () -> shouldContainIsoControlCharacter("\u005Cr"), // carriage return () -> shouldContainIsoControlCharacter("\r"), () -> shouldNotContainIsoControlCharacter(null), () -> shouldNotContainIsoControlCharacter(""), () -> shouldNotContainIsoControlCharacter("hello-world"), () -> shouldNotContainIsoControlCharacter("0123456789"), () -> shouldNotContainIsoControlCharacter("$-_=+!@.,"), () -> shouldNotContainIsoControlCharacter(" "), () -> shouldNotContainIsoControlCharacter("hello world") ); // @formatter:on } @Test void replaceControlCharacters() { assertNull(replaceIsoControlCharacters(null, "")); assertEquals("", replaceIsoControlCharacters("", ".")); assertEquals("", replaceIsoControlCharacters("\t\n\r", "")); assertEquals("...", replaceIsoControlCharacters("\t\n\r", ".")); assertEquals("...", replaceIsoControlCharacters("\u005Ct\u005Cn\u005Cr", ".")); assertEquals("abc", replaceIsoControlCharacters("abc", "?")); assertEquals("...", replaceIsoControlCharacters("...", "?")); assertThrows(PreconditionViolationException.class, () -> replaceIsoControlCharacters("", null)); } @Test void replaceWhitespaces() { assertNull(replaceWhitespaceCharacters(null, "")); assertEquals("", replaceWhitespaceCharacters("", ".")); assertEquals("", replaceWhitespaceCharacters("\t\n\r", "")); assertEquals("...", replaceWhitespaceCharacters("\t\n\r", ".")); assertEquals("...", replaceWhitespaceCharacters("\u005Ct\u005Cn\u005Cr", ".")); assertEquals("abc", replaceWhitespaceCharacters("abc", "?")); assertEquals("...", replaceWhitespaceCharacters("...", "?")); assertEquals(" ", replaceWhitespaceCharacters(" ", " ")); assertEquals(" ", replaceWhitespaceCharacters("\u000B", " ")); assertEquals(" ", replaceWhitespaceCharacters("\f", " ")); assertThrows(PreconditionViolationException.class, () -> replaceWhitespaceCharacters("", null)); } @Test void nullSafeToStringChecks() { assertEquals("null", nullSafeToString(null)); assertEquals("", nullSafeToString("")); assertEquals("\t", nullSafeToString("\t")); assertEquals("foo", nullSafeToString("foo")); assertEquals("3.14", nullSafeToString(Double.valueOf("3.14"))); assertEquals("[1, 2, 3]", nullSafeToString(new int[] { 1, 2, 3 })); assertEquals("[a, b, c]", nullSafeToString(new char[] { 'a', 'b', 'c' })); assertEquals("[foo, bar]", nullSafeToString(new String[] { "foo", "bar" })); assertEquals("[34, 42]", nullSafeToString(new Integer[] { 34, 42 })); assertEquals("[[2, 4], [3, 9]]", nullSafeToString(new Integer[][] { { 2, 4 }, { 3, 9 } })); } @Test void nullSafeToStringForObjectWhoseToStringImplementationReturnsNull() { assertEquals("null", nullSafeToString(new ToStringReturnsNull())); } @Test void nullSafeToStringForObjectWhoseToStringImplementationThrowsAnException() { assertThat(nullSafeToString(new ToStringThrowsException()))// .startsWith(ToStringThrowsException.class.getName() + "@"); } private void shouldContainWhitespace(String str) { assertTrue(containsWhitespace(str), () -> String.format("'%s' should contain whitespace", str)); assertFalse(doesNotContainWhitespace(str), () -> String.format("'%s' should contain whitespace", str)); } private void shouldNotContainWhitespace(String str) { assertTrue(doesNotContainWhitespace(str), () -> String.format("'%s' should not contain whitespace", str)); assertFalse(containsWhitespace(str), () -> String.format("'%s' should not contain whitespace", str)); } private void shouldContainIsoControlCharacter(String str) { assertTrue(containsIsoControlCharacter(str), () -> String.format("'%s' should contain ISO control character", str)); assertFalse(doesNotContainIsoControlCharacter(str), () -> String.format("'%s' should contain ISO control character", str)); } private void shouldNotContainIsoControlCharacter(String str) { assertTrue(doesNotContainIsoControlCharacter(str), () -> String.format("'%s' should not contain ISO control character", str)); assertFalse(containsIsoControlCharacter(str), () -> String.format("'%s' should not contain ISO control character", str)); } private static class ToStringReturnsNull { @Override public String toString() { return null; } } private static class ToStringThrowsException { @Override public String toString() { throw new RuntimeException("Boom!"); } } } ToStringBuilderTests.java000066400000000000000000000111551455764576500337700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.LinkedHashMap; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link ToStringBuilder}. * * @since 1.0 */ class ToStringBuilderTests { @Test void withNullObject() { assertThrows(PreconditionViolationException.class, () -> new ToStringBuilder((Object) null)); } @Test void withNullClass() { assertThrows(PreconditionViolationException.class, () -> new ToStringBuilder((Class) null)); } @Test void appendWithIllegalName() { var builder = new ToStringBuilder(""); assertThrows(PreconditionViolationException.class, () -> builder.append(null, "")); assertThrows(PreconditionViolationException.class, () -> builder.append("", "")); assertThrows(PreconditionViolationException.class, () -> builder.append(" ", "")); } @Test void withZeroFields() { assertEquals("RoleModel []", new ToStringBuilder(new RoleModel()).toString()); assertEquals("RoleModel []", new ToStringBuilder(RoleModel.class).toString()); } @Test void withOneField() { assertEquals("RoleModel [name = 'Dilbert']", new ToStringBuilder(new RoleModel()).append("name", "Dilbert").toString()); } @Test void withNullField() { assertEquals("RoleModel [name = null]", new ToStringBuilder(new RoleModel()).append("name", null).toString()); } @Test void withTwoFields() { assertEquals("RoleModel [name = 'Dilbert', age = 42]", new ToStringBuilder(new RoleModel()).append("name", "Dilbert").append("age", 42).toString()); } @Test void withIntegerArrayField() { assertEquals("RoleModel [magic numbers = [1, 42, 99]]", new ToStringBuilder(new RoleModel()).append("magic numbers", new Integer[] { 1, 42, 99 }).toString()); } @Test void withIntArrayField() { assertEquals("RoleModel [magic numbers = [1, 42, 23]]", new ToStringBuilder(new RoleModel()).append("magic numbers", new int[] { 1, 42, 23 }).toString()); } @Test void withCharArrayField() { assertEquals("RoleModel [magic characters = [a, b]]", new ToStringBuilder(new RoleModel()).append("magic characters", new char[] { 'a', 'b' }).toString()); } @Test void withPrimitiveBooleanArrayField() { assertEquals("RoleModel [booleans = [true, false, true]]", new ToStringBuilder(new RoleModel()).append("booleans", new boolean[] { true, false, true }).toString()); } @Test void withShortArrayField() { assertEquals("RoleModel [values = [23, 42]]", new ToStringBuilder(new RoleModel()).append("values", new short[] { 23, 42 }).toString()); } @Test void withByteArrayField() { assertEquals("RoleModel [values = [23, 42]]", new ToStringBuilder(new RoleModel()).append("values", new byte[] { 23, 42 }).toString()); } @Test void withPrimitiveLongArrayField() { assertEquals("RoleModel [values = [23, 42]]", new ToStringBuilder(new RoleModel()).append("values", new long[] { 23, 42 }).toString()); } @Test void withPrimitiveFloatArrayField() { assertEquals("RoleModel [values = [23.45, 17.13]]", new ToStringBuilder(new RoleModel()).append("values", new float[] { 23.45f, 17.13f }).toString()); } @Test void withPrimitiveDoubleArrayField() { assertEquals("RoleModel [values = [23.45, 17.13]]", new ToStringBuilder(new RoleModel()).append("values", new double[] { 23.45d, 17.13d }).toString()); } @Test @SuppressWarnings("serial") void withMapField() { // @formatter:off Map map = new LinkedHashMap<>() {{ put("foo", 42); put("bar", "enigma"); }}; // @formatter:on assertEquals("RoleModel [mystery map = {foo=42, bar=enigma}]", new ToStringBuilder(new RoleModel()).append("mystery map", map).toString()); } @Test void withDemoImplementation() { var roleModel = new RoleModel("Dilbert", 42); assertEquals("RoleModel [name = 'Dilbert', age = 42]", roleModel.toString()); } static class RoleModel { String name; int age; RoleModel() { } RoleModel(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { // @formatter:off return new ToStringBuilder(this) .append("name", this.name) .append("age", this.age) .toString(); // @formatter:on } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/000077500000000000000000000000001455764576500305335ustar00rootroot00000000000000AExecutionConditionClass.java000066400000000000000000000014651455764576500362260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; /** * @since 5.7 */ public class AExecutionConditionClass implements ExecutionCondition { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return ConditionEvaluationResult.enabled("for Class Name Filter Tests"); } } ATestExecutionListenerClass.java000066400000000000000000000010151455764576500367140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; import org.junit.platform.launcher.TestExecutionListener; /** * @since 5.7 */ public class ATestExecutionListenerClass implements TestExecutionListener { } AVanillaEmpty.java000066400000000000000000000006431455764576500340300ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; /** * @since 5.7 */ public class AVanillaEmpty { } BExecutionConditionClass.java000066400000000000000000000014651455764576500362270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; /** * @since 5.7 */ public class BExecutionConditionClass implements ExecutionCondition { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { return ConditionEvaluationResult.enabled("for Class Name Filter Tests"); } } BTestExecutionListenerClass.java000066400000000000000000000010151455764576500367150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; import org.junit.platform.launcher.TestExecutionListener; /** * @since 5.7 */ public class BTestExecutionListenerClass implements TestExecutionListener { } BVanillaEmpty.java000066400000000000000000000006431455764576500340310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; /** * @since 5.7 */ public class BVanillaEmpty { } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/classes/CustomType.java000066400000000000000000000007311455764576500335130ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.classes; public class CustomType { void customMethod(NestedType arg) { } public static class NestedType { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/000077500000000000000000000000001455764576500277405ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/ClassLevelDir.java000066400000000000000000000012231455764576500332750ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Mimics {@code @TempDir}. */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ClassLevelDir { } InstanceLevelDir.java000066400000000000000000000012261455764576500337200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Mimics {@code @TempDir}. */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface InstanceLevelDir { } SuperclassWithStaticPackagePrivateBeforeMethod.java000066400000000000000000000011101455764576500417400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1; import org.junit.jupiter.api.BeforeAll; /** * @see https://github.com/junit-team/junit5/issues/3553 */ public class SuperclassWithStaticPackagePrivateBeforeMethod { @BeforeAll static void before() { // no-op } } SuperclassWithStaticPackagePrivateTempDirField.java000066400000000000000000000010571455764576500417170ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1; import java.nio.file.Path; /** * @see https://github.com/junit-team/junit5/issues/3553 */ public class SuperclassWithStaticPackagePrivateTempDirField { @ClassLevelDir static Path tempDir; } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/000077500000000000000000000000001455764576500312335ustar00rootroot00000000000000SubclassWithNonStaticPackagePrivateBeforeMethod.java000066400000000000000000000013361455764576500433530ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1.subpkg; import org.junit.jupiter.api.BeforeEach; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateBeforeMethod; /** * @see https://github.com/junit-team/junit5/issues/3553 */ public class SubclassWithNonStaticPackagePrivateBeforeMethod extends SuperclassWithStaticPackagePrivateBeforeMethod { @BeforeEach void before() { // no-op } } SubclassWithNonStaticPackagePrivateTempDirField.java000066400000000000000000000014051455764576500433150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.commons.util.pkg1.subpkg; import java.nio.file.Path; import org.junit.platform.commons.util.pkg1.InstanceLevelDir; import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateTempDirField; /** * @see https://github.com/junit-team/junit5/issues/3553 */ public class SubclassWithNonStaticPackagePrivateTempDirField extends SuperclassWithStaticPackagePrivateTempDirField { @InstanceLevelDir Path tempDir; } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/000077500000000000000000000000001455764576500261105ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java000066400000000000000000000167201455764576500327140ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.commons.util.ReflectionUtils.getFullyQualifiedMethodName; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.EnumMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.function.Executable; import org.junit.platform.console.options.Details; import org.junit.platform.console.options.Theme; import org.opentest4j.TestAbortedException; /** * @since 1.0 */ class ConsoleDetailsTests { @TestFactory @DisplayName("Basic tests and annotations usage") List basic() { return scanContainerClassAndCreateDynamicTests(BasicTestCase.class); } @TestFactory @DisplayName("Skipped and disabled tests") List skipped() { return scanContainerClassAndCreateDynamicTests(SkipTestCase.class); } @TestFactory @DisplayName("Failed tests") List failed() { return scanContainerClassAndCreateDynamicTests(FailTestCase.class); } @TestFactory @DisplayName("Tests publishing report entries") List reports() { return scanContainerClassAndCreateDynamicTests(ReportTestCase.class); } private List scanContainerClassAndCreateDynamicTests(Class containerClass) { var containerName = containerClass.getSimpleName().replace("TestCase", ""); // String containerName = containerClass.getSimpleName(); List nodes = new ArrayList<>(); Map> map = new EnumMap<>(Details.class); for (var method : findMethods(containerClass, m -> m.isAnnotationPresent(Test.class))) { var methodName = method.getName(); var types = method.getParameterTypes(); for (var details : Details.values()) { var tests = map.computeIfAbsent(details, key -> new ArrayList<>()); for (var theme : Theme.values()) { var caption = containerName + "-" + methodName + "-" + details + "-" + theme; String[] args = { // "--include-engine", "junit-jupiter", // "--details", details.name(), // "--details-theme", theme.name(), // "--disable-ansi-colors", // "--disable-banner", // "--include-classname", containerClass.getCanonicalName(), // "--select-method", getFullyQualifiedMethodName(containerClass, methodName, types) // }; var displayName = methodName + "() " + theme.name(); var dirName = "console/details/" + containerName.toLowerCase(); var outName = caption + ".out.txt"; var runner = new Runner(dirName, outName, args); var source = toUri(dirName, outName).orElse(null); tests.add(dynamicTest(displayName, source, runner)); } } } var source = new File("src/test/resources/console/details").toURI(); map.forEach((details, tests) -> nodes.add(dynamicContainer(details.name(), source, tests.stream()))); return nodes; } @DisplayName("Basic") static class BasicTestCase { @Test void empty() { } @Test @DisplayName(".oO fancy display name Oo.") void changeDisplayName() { } } @DisplayName("Skip") static class SkipTestCase { @Test @Disabled("single line skip reason") void skipWithSingleLineReason() { } @Test @Disabled("multi\nline\nfail\nmessage") void skipWithMultiLineMessage() { } } @DisplayName("Fail") static class FailTestCase { @Test void failWithSingleLineMessage() { fail("single line fail message"); } @Test void failWithMultiLineMessage() { fail("multi\nline\nfail\nmessage"); } } @DisplayName("Report") static class ReportTestCase { @Test void reportSingleMessage(TestReporter reporter) { reporter.publishEntry("foo"); } @Test void reportMultipleMessages(TestReporter reporter) { reporter.publishEntry("foo"); reporter.publishEntry("bar"); } @Test void reportSingleEntryWithSingleMapping(TestReporter reporter) { reporter.publishEntry("foo", "bar"); } @Test void reportMultiEntriesWithSingleMapping(TestReporter reporter) { reporter.publishEntry("foo", "bar"); reporter.publishEntry("far", "boo"); } @Test void reportMultiEntriesWithMultiMappings(TestReporter reporter) { Map values = new LinkedHashMap<>(); values.put("user name", "dk38"); values.put("award year", "1974"); reporter.publishEntry(values); reporter.publishEntry("single", "mapping"); Map more = new LinkedHashMap<>(); more.put("user name", "st77"); more.put("award year", "1977"); more.put("last seen", "2001"); reporter.publishEntry(more); } } private static class Runner implements Executable { private final String dirName; private final String outName; private final String[] args; private Runner(String dirName, String outName, String... args) { this.dirName = dirName; this.outName = outName; this.args = args; } @Override public void execute() throws Throwable { var wrapper = new ConsoleLauncherWrapper(); var result = wrapper.execute(Optional.empty(), args); var optionalUri = toUri(dirName, outName); if (optionalUri.isEmpty()) { if (Boolean.getBoolean("org.junit.platform.console.ConsoleDetailsTests.writeResultOut")) { // do not use Files.createTempDirectory(prefix) as we want one folder for one container var temp = Paths.get(System.getProperty("java.io.tmpdir"), dirName.replace('/', '-')); Files.createDirectories(temp); var path = Files.writeString(temp.resolve(outName), result.out); throw new TestAbortedException( format("resource `%s` not found\nwrote console stdout to: %s/%s", dirName, outName, path)); } fail("could not load resource named `" + dirName + "/" + outName + "`"); } var path = Paths.get(optionalUri.get()); assumeTrue(Files.exists(path), "path does not exist: " + path); assumeTrue(Files.isReadable(path), "can not read: " + path); var expectedLines = Files.readAllLines(path, UTF_8); var actualLines = List.of(result.out.split("\\R")); assertLinesMatch(expectedLines, actualLines); } } static Optional toUri(String dirName, String outName) { var resourceName = dirName + "/" + outName; var url = ConsoleDetailsTests.class.getClassLoader().getResource(resourceName); if (url == null) { return Optional.empty(); } try { return Optional.of(url.toURI()); } catch (URISyntaxException e) { return Optional.empty(); } } } ConsoleLauncherIntegrationTests.java000066400000000000000000000061631455764576500352150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; /** * @since 1.0 */ class ConsoleLauncherIntegrationTests { @Test void executeWithoutArgumentsFailsAndPrintsHelpInformation() { var result = new ConsoleLauncherWrapper().execute(-1); assertAll("empty args array results in display of help information and an exception stacktrace", // () -> assertThat(result.err).contains("help information"), // () -> assertThat(result.err).contains( "Please specify an explicit selector option or use --scan-class-path or --scan-modules") // ); } @ParameterizedTest @ValueSource(strings = { // "-e junit-jupiter -p org.junit.platform.console.subpackage", // "execute -e junit-jupiter -p org.junit.platform.console.subpackage" // }) void executeWithoutExcludeClassnameOptionDoesNotExcludeClassesAndMustIncludeAllClassesMatchingTheStandardClassnamePattern( final String line) { String[] args = line.split(" "); assertEquals(9, new ConsoleLauncherWrapper().execute(args).getTestsFoundCount()); } @ParameterizedTest @ValueSource(strings = { "-e junit-jupiter -p org.junit.platform.console.subpackage --exclude-classname" + " ^org\\.junit\\.platform\\.console\\.subpackage\\..*", "execute -e junit-jupiter -p org.junit.platform.console.subpackage --exclude-classname" + " ^org\\.junit\\.platform\\.console\\.subpackage\\..*" // }) void executeWithExcludeClassnameOptionExcludesClasses(final String line) { String[] args = line.split(" "); var result = new ConsoleLauncherWrapper().execute(args); assertAll("all subpackage test classes are excluded by the class name filter", // () -> assertArrayEquals(args, result.args), // () -> assertEquals(0, result.code), // () -> assertEquals(0, result.getTestsFoundCount()) // ); } @ParameterizedTest @ValueSource(strings = { // "-e junit-jupiter -o java.base", "-e junit-jupiter --select-module java.base", // "execute -e junit-jupiter -o java.base", "execute -e junit-jupiter --select-module java.base" // }) void executeSelectingModuleNames(final String line) { String[] args1 = line.split(" "); assertEquals(0, new ConsoleLauncherWrapper().execute(args1).getTestsFoundCount()); } @ParameterizedTest @ValueSource(strings = { "-e junit-jupiter --scan-modules", "execute -e junit-jupiter --scan-modules" }) void executeScanModules(final String line) { String[] args1 = line.split(" "); assertEquals(0, new ConsoleLauncherWrapper().execute(args1).getTestsFoundCount()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherTests.java000066400000000000000000000062351455764576500330700ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.io.PrintWriter; import java.io.StringWriter; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.console.tasks.ConsoleTestExecutor; /** * @since 1.0 */ class ConsoleLauncherTests { private final StringWriter stringWriter = new StringWriter(); private final PrintWriter printSink = new PrintWriter(stringWriter); @ParameterizedTest(name = "{0}") @MethodSource("commandsWithEmptyOptionExitCodes") void displayHelp(String command) { var consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, printSink, printSink); var exitCode = consoleLauncher.run(command, "--help").getExitCode(); assertEquals(0, exitCode); assertThat(stringWriter.toString()).contains("--help", "--disable-banner" /* ... */); } @ParameterizedTest(name = "{0}") @MethodSource("commandsWithEmptyOptionExitCodes") void displayBanner(String command) { var consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, printSink, printSink); consoleLauncher.run(command); assertThat(stringWriter.toString()).contains("Thanks for using JUnit!"); } @ParameterizedTest(name = "{0}") @MethodSource("commandsWithEmptyOptionExitCodes") void disableBanner(String command, int expectedExitCode) { var consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, printSink, printSink); var exitCode = consoleLauncher.run(command, "--disable-banner").getExitCode(); assertEquals(expectedExitCode, exitCode); assertThat(stringWriter.toString()).doesNotContain("Thanks for using JUnit!"); } @ParameterizedTest(name = "{0}") @MethodSource("commandsWithEmptyOptionExitCodes") void executeWithUnknownCommandLineOption(String command) { var consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, printSink, printSink); var exitCode = consoleLauncher.run(command, "--all").getExitCode(); assertEquals(-1, exitCode); assertThat(stringWriter.toString()).contains("Unknown option: '--all'").contains("Usage:"); } @ParameterizedTest(name = "{0}") @MethodSource("commandsWithEmptyOptionExitCodes") void executeWithoutCommandLineOptions(String command, int expectedExitCode) { var consoleLauncher = new ConsoleLauncher(ConsoleTestExecutor::new, printSink, printSink); var actualExitCode = consoleLauncher.run(command).getExitCode(); assertEquals(expectedExitCode, actualExitCode); } static Stream commandsWithEmptyOptionExitCodes() { return Stream.of( // arguments("execute", -1), // arguments("discover", -1), // arguments("engines", 0) // ); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapper.java000066400000000000000000000036601455764576500334050ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Optional; import org.junit.platform.console.tasks.ConsoleTestExecutor; /** * @since 1.0 */ class ConsoleLauncherWrapper { private final StringWriter out = new StringWriter(); private final StringWriter err = new StringWriter(); private final ConsoleLauncher consoleLauncher; ConsoleLauncherWrapper() { this(ConsoleTestExecutor::new); } private ConsoleLauncherWrapper(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { var outWriter = new PrintWriter(out, false); var errWriter = new PrintWriter(err, false); this.consoleLauncher = new ConsoleLauncher(consoleTestExecutorFactory, outWriter, errWriter); } public ConsoleLauncherWrapperResult execute(String... args) { return execute(0, args); } public ConsoleLauncherWrapperResult execute(int expectedExitCode, String... args) { return execute(Optional.of(expectedExitCode), args); } public ConsoleLauncherWrapperResult execute(Optional expectedCode, String... args) { var result = consoleLauncher.run(args); var code = result.getExitCode(); var outText = out.toString(); var errText = err.toString(); if (expectedCode.isPresent()) { int expectedValue = expectedCode.get(); assertEquals(expectedValue, code, "ConsoleLauncher execute code mismatch!"); if (expectedValue != 0) { assertThat(errText).isNotBlank(); } } return new ConsoleLauncherWrapperResult(args, outText, errText, result); } } ConsoleLauncherWrapperResult.java000066400000000000000000000073241455764576500345260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console; import java.io.PrintWriter; import java.util.List; import org.junit.platform.console.options.CommandResult; import org.junit.platform.launcher.listeners.TestExecutionSummary; /** * @since 1.0 */ class ConsoleLauncherWrapperResult implements TestExecutionSummary { final String[] args; final String out; final String err; final int code; private final TestExecutionSummary summary; ConsoleLauncherWrapperResult(String[] args, String out, String err, CommandResult result) { this.args = args; this.out = out; this.err = err; this.code = result.getExitCode(); this.summary = (TestExecutionSummary) result.getValue() // .filter(it -> it instanceof TestExecutionSummary) // .orElse(null); } private void checkTestExecutionSummaryState() { if (summary == null) { throw new IllegalStateException("TestExecutionSummary not assigned. Exit code is: " + code); } } @Override public long getTimeStarted() { checkTestExecutionSummaryState(); return summary.getTimeStarted(); } @Override public long getTimeFinished() { checkTestExecutionSummaryState(); return summary.getTimeFinished(); } @Override public long getTotalFailureCount() { checkTestExecutionSummaryState(); return summary.getTotalFailureCount(); } @Override public long getContainersFoundCount() { checkTestExecutionSummaryState(); return summary.getContainersFoundCount(); } @Override public long getContainersStartedCount() { checkTestExecutionSummaryState(); return summary.getContainersStartedCount(); } @Override public long getContainersSkippedCount() { checkTestExecutionSummaryState(); return summary.getContainersSkippedCount(); } @Override public long getContainersAbortedCount() { checkTestExecutionSummaryState(); return summary.getContainersAbortedCount(); } @Override public long getContainersSucceededCount() { checkTestExecutionSummaryState(); return summary.getContainersSucceededCount(); } @Override public long getContainersFailedCount() { checkTestExecutionSummaryState(); return summary.getContainersFailedCount(); } @Override public long getTestsFoundCount() { checkTestExecutionSummaryState(); return summary.getTestsFoundCount(); } @Override public long getTestsStartedCount() { checkTestExecutionSummaryState(); return summary.getTestsStartedCount(); } @Override public long getTestsSkippedCount() { checkTestExecutionSummaryState(); return summary.getTestsSkippedCount(); } @Override public long getTestsAbortedCount() { checkTestExecutionSummaryState(); return summary.getTestsAbortedCount(); } @Override public long getTestsSucceededCount() { checkTestExecutionSummaryState(); return summary.getTestsSucceededCount(); } @Override public long getTestsFailedCount() { checkTestExecutionSummaryState(); return summary.getTestsFailedCount(); } @Override public void printTo(PrintWriter writer) { checkTestExecutionSummaryState(); summary.printTo(writer); } @Override public void printFailuresTo(PrintWriter writer) { checkTestExecutionSummaryState(); summary.printFailuresTo(writer); } @Override public void printFailuresTo(PrintWriter writer, int maxStackTraceLines) { checkTestExecutionSummaryState(); summary.printFailuresTo(writer, maxStackTraceLines); } @Override public List getFailures() { checkTestExecutionSummaryState(); return summary.getFailures(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/options/000077500000000000000000000000001455764576500276035ustar00rootroot00000000000000CommandLineOptionsParsingTests.java000066400000000000000000000715411455764576500365100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathResource; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectFile; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModule; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; /** * @since 1.10 */ class CommandLineOptionsParsingTests { @Test void parseNoArguments() { String[] noArguments = {}; var options = parse(noArguments); // @formatter:off assertAll( () -> assertFalse(options.output.isAnsiColorOutputDisabled()), () -> assertEquals(TestConsoleOutputOptions.DEFAULT_DETAILS, options.output.getDetails()), () -> assertFalse(options.discovery.isScanClasspath()), () -> assertEquals(List.of(STANDARD_INCLUDE_PATTERN), options.discovery.getIncludedClassNamePatterns()), () -> assertEquals(List.of(), options.discovery.getExcludedClassNamePatterns()), () -> assertEquals(List.of(), options.discovery.getIncludedPackages()), () -> assertEquals(List.of(), options.discovery.getExcludedPackages()), () -> assertEquals(List.of(), options.discovery.getIncludedTagExpressions()), () -> assertEquals(List.of(), options.discovery.getExcludedTagExpressions()), () -> assertEquals(List.of(), options.discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(), options.discovery.getSelectedUris()), () -> assertEquals(List.of(), options.discovery.getSelectedFiles()), () -> assertEquals(List.of(), options.discovery.getSelectedDirectories()), () -> assertEquals(List.of(), options.discovery.getSelectedModules()), () -> assertEquals(List.of(), options.discovery.getSelectedPackages()), () -> assertEquals(List.of(), options.discovery.getSelectedMethods()), () -> assertEquals(List.of(), options.discovery.getSelectedClasspathEntries()), () -> assertEquals(Map.of(), options.discovery.getConfigurationParameters()) ); // @formatter:on } @Test void parseSwitches() { // @formatter:off assertAll( () -> assertTrue(parse("--disable-ansi-colors").output.isAnsiColorOutputDisabled(), "disable ansi"), () -> assertTrue(parse("--scan-class-path").discovery.isScanClasspath(), "scan class path") ); // @formatter:on } @ParameterizedTest @EnumSource void parseValidDetails(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(Details.VERBOSE, type.parseArgLine("--details verbose").output.getDetails()), () -> assertEquals(Details.TREE, type.parseArgLine("--details tree").output.getDetails()), () -> assertEquals(Details.FLAT, type.parseArgLine("--details flat").output.getDetails()), () -> assertEquals(Details.NONE, type.parseArgLine("--details NONE").output.getDetails()), () -> assertEquals(Details.NONE, type.parseArgLine("--details none").output.getDetails()), () -> assertEquals(Details.NONE, type.parseArgLine("--details None").output.getDetails()) ); // @formatter:on } @Test void parseInvalidDetails() { assertOptionWithMissingRequiredArgumentThrowsException("--details"); } @ParameterizedTest @EnumSource void parseValidDetailsTheme(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(Theme.ASCII, type.parseArgLine("--details-theme ascii").output.getTheme()), () -> assertEquals(Theme.ASCII, type.parseArgLine("--details-theme ASCII").output.getTheme()), () -> assertEquals(Theme.UNICODE, type.parseArgLine("--details-theme unicode").output.getTheme()), () -> assertEquals(Theme.UNICODE, type.parseArgLine("--details-theme UNICODE").output.getTheme()), () -> assertEquals(Theme.UNICODE, type.parseArgLine("--details-theme uniCode").output.getTheme()) ); // @formatter:on } @Test void parseInvalidDetailsTheme() { assertOptionWithMissingRequiredArgumentThrowsException("--details-theme"); } @ParameterizedTest @EnumSource void parseValidIncludeClassNamePatterns(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(".*Test"), type.parseArgLine("-n .*Test").discovery.getIncludedClassNamePatterns()), () -> assertEquals(List.of(".*Test", ".*Tests"), type.parseArgLine("--include-classname .*Test --include-classname .*Tests").discovery.getIncludedClassNamePatterns()), () -> assertEquals(List.of(".*Test"), type.parseArgLine("--include-classname=.*Test").discovery.getIncludedClassNamePatterns()) ); // @formatter:on } @ParameterizedTest @EnumSource void parseValidExcludeClassNamePatterns(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(".*Test"), type.parseArgLine("-N .*Test").discovery.getExcludedClassNamePatterns()), () -> assertEquals(List.of(".*Test", ".*Tests"), type.parseArgLine("--exclude-classname .*Test --exclude-classname .*Tests").discovery.getExcludedClassNamePatterns()), () -> assertEquals(List.of(".*Test"), type.parseArgLine("--exclude-classname=.*Test").discovery.getExcludedClassNamePatterns()) ); // @formatter:on } @Test void usesDefaultClassNamePatternWithoutExplicitArgument() throws Exception { assertEquals(List.of(STANDARD_INCLUDE_PATTERN), ArgsType.args.parseArgLine("").discovery.getIncludedClassNamePatterns()); } @Test void parseInvalidIncludeClassNamePatterns() { assertOptionWithMissingRequiredArgumentThrowsException("-n", "--include-classname"); } @Test void parseInvalidExcludeClassNamePatterns() { assertOptionWithMissingRequiredArgumentThrowsException("-N", "--exclude-classname"); } @ParameterizedTest @EnumSource void parseValidIncludedPackages(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("org.junit.included"), type.parseArgLine("--include-package org.junit.included").discovery.getIncludedPackages()), () -> assertEquals(List.of("org.junit.included"), type.parseArgLine("--include-package=org.junit.included").discovery.getIncludedPackages()), () -> assertEquals(List.of("org.junit.included1", "org.junit.included2"), type.parseArgLine("--include-package org.junit.included1 --include-package org.junit.included2").discovery.getIncludedPackages()) ); // @formatter:on } @ParameterizedTest @EnumSource void parseValidExcludedPackages(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("org.junit.excluded"), type.parseArgLine("--exclude-package org.junit.excluded").discovery.getExcludedPackages()), () -> assertEquals(List.of("org.junit.excluded"), type.parseArgLine("--exclude-package=org.junit.excluded").discovery.getExcludedPackages()), () -> assertEquals(List.of("org.junit.excluded1", "org.junit.excluded2"), type.parseArgLine("--exclude-package org.junit.excluded1 --exclude-package org.junit.excluded2").discovery.getExcludedPackages()) ); // @formatter:on } @ParameterizedTest @EnumSource void parseValidIncludedTags(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("fast"), type.parseArgLine("-t fast").discovery.getIncludedTagExpressions()), () -> assertEquals(List.of("fast"), type.parseArgLine("--include-tag fast").discovery.getIncludedTagExpressions()), () -> assertEquals(List.of("fast"), type.parseArgLine("--include-tag=fast").discovery.getIncludedTagExpressions()), () -> assertEquals(List.of("fast", "slow"), type.parseArgLine("-t fast -t slow").discovery.getIncludedTagExpressions()) ); // @formatter:on } @Test void parseInvalidIncludedTags() { assertOptionWithMissingRequiredArgumentThrowsException("-t", "--include-tag"); } @ParameterizedTest @EnumSource void parseValidExcludedTags(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("fast"), type.parseArgLine("-T fast").discovery.getExcludedTagExpressions()), () -> assertEquals(List.of("fast"), type.parseArgLine("--exclude-tag fast").discovery.getExcludedTagExpressions()), () -> assertEquals(List.of("fast"), type.parseArgLine("--exclude-tag=fast").discovery.getExcludedTagExpressions()), () -> assertEquals(List.of("fast", "slow"), type.parseArgLine("-T fast -T slow").discovery.getExcludedTagExpressions()) ); // @formatter:on } @Test void parseInvalidExcludedTags() { assertOptionWithMissingRequiredArgumentThrowsException("-T", "--exclude-tag"); } @ParameterizedTest @EnumSource void parseValidIncludedEngines(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("junit-jupiter"), type.parseArgLine("-e junit-jupiter").discovery.getIncludedEngines()), () -> assertEquals(List.of("junit-vintage"), type.parseArgLine("--include-engine junit-vintage").discovery.getIncludedEngines()), () -> assertEquals(List.of(), type.parseArgLine("").discovery.getIncludedEngines()) ); // @formatter:on } @Test void parseInvalidIncludedEngines() { assertOptionWithMissingRequiredArgumentThrowsException("-e", "--include-engine"); } @ParameterizedTest @EnumSource void parseValidExcludedEngines(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of("junit-jupiter"), type.parseArgLine("-E junit-jupiter").discovery.getExcludedEngines()), () -> assertEquals(List.of("junit-vintage"), type.parseArgLine("--exclude-engine junit-vintage").discovery.getExcludedEngines()), () -> assertEquals(List.of(), type.parseArgLine("").discovery.getExcludedEngines()) ); // @formatter:on } @Test void parseInvalidExcludedEngines() { assertOptionWithMissingRequiredArgumentThrowsException("-E", "--exclude-engine"); } @ParameterizedTest @EnumSource void parseValidAdditionalClasspathEntries(ArgsType type) { var dir = Paths.get("."); // @formatter:off assertAll( () -> assertEquals(List.of(dir), type.parseArgLine("-cp .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--cp .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("-classpath .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("-classpath=.").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--classpath .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--classpath=.").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--class-path .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--class-path=.").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir, Path.of("lib/some.jar")), type.parseArgLine("-cp . -cp lib/some.jar").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir, Path.of("lib/some.jar")), type.parseArgLine("-cp ." + File.pathSeparator + "lib/some.jar").discovery.getAdditionalClasspathEntries()) ); // @formatter:on } @Test @EnabledOnOs(OS.WINDOWS) void parseValidAndAbsoluteAdditionalClasspathEntries() throws Exception { ArgsType type = ArgsType.args; assertEquals(List.of(Path.of("C:\\a.jar")), type.parseArgLine("-cp C:\\a.jar").discovery.getAdditionalClasspathEntries()); assertEquals(List.of(Path.of("C:\\foo.jar"), Path.of("D:\\bar.jar")), type.parseArgLine("-cp C:\\foo.jar;D:\\bar.jar").discovery.getAdditionalClasspathEntries()); } @Test void parseInvalidAdditionalClasspathEntries() { assertOptionWithMissingRequiredArgumentThrowsException("-cp", "--classpath", "--class-path"); } @Test void parseInvalidXmlReportsDirs() { assertOptionWithMissingRequiredArgumentThrowsException("--reports-dir"); } @ParameterizedTest @EnumSource void parseValidUriSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-u file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--u file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-select-uri file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-select-uri=file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--select-uri file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--select-uri=file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt"), selectUri("https://example")), type.parseArgLine("-u file:///foo.txt -u https://example").discovery.getSelectedUris()) ); // @formatter:on } @Test void parseInvalidUriSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-u", "--select-uri", "-u unknown-scheme:"); } @ParameterizedTest @EnumSource void parseValidFileSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-f foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--f foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-select-file foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-select-file=foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--select-file foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--select-file=foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt"), selectFile("bar.csv")), type.parseArgLine("-f foo.txt -f bar.csv").discovery.getSelectedFiles()) ); // @formatter:on } @Test void parseInvalidFileSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-f", "--select-file"); } @ParameterizedTest @EnumSource void parseValidDirectorySelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-d foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--d foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-select-directory foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-select-directory=foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--select-directory foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--select-directory=foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar"), selectDirectory("bar/qux")), type.parseArgLine("-d foo/bar -d bar/qux").discovery.getSelectedDirectories()) ); // @formatter:on } @Test void parseInvalidDirectorySelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-d", "--select-directory"); } @ParameterizedTest @EnumSource void parseValidModuleSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-o com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--o com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-select-module com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-select-module=com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--select-module com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--select-module=com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo"), selectModule("com.example.bar")), type.parseArgLine("-o com.acme.foo -o com.example.bar").discovery.getSelectedModules()) ); // @formatter:on } @Test void parseInvalidModuleSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-o", "--select-module"); } @ParameterizedTest @EnumSource void parseValidPackageSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-p com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--p com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-select-package com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-select-package=com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--select-package com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--select-package=com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo"), selectPackage("com.example.bar")), type.parseArgLine("-p com.acme.foo -p com.example.bar").discovery.getSelectedPackages()) ); // @formatter:on } @Test void parseInvalidPackageSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-p", "--select-package"); } @ParameterizedTest @EnumSource void parseValidClassSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-c com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--c com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-select-class com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-select-class=com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--select-class com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--select-class=com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo"), selectClass("com.example.Bar")), type.parseArgLine("-c com.acme.Foo -c com.example.Bar").discovery.getSelectedClasses()) ); // @formatter:on } @Test void parseInvalidClassSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-c", "--select-class"); } @ParameterizedTest @EnumSource void parseValidMethodSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-m com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--m com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-select-method com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-select-method=com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--select-method com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--select-method=com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()"), selectMethod("com.example.Bar#method(java.lang.Object)")), type.parseArgLine("-m com.acme.Foo#m() -m com.example.Bar#method(java.lang.Object)").discovery.getSelectedMethods()) ); // @formatter:on } @Test void parseInvalidMethodSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-m", "--select-method"); } @ParameterizedTest @EnumSource void parseValidClasspathResourceSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-r /foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--r /foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-select-resource /foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-select-resource=/foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--select-resource /foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--select-resource=/foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv"), selectClasspathResource("bar.json")), type.parseArgLine("-r /foo.csv -r bar.json").discovery.getSelectedClasspathResources()) ); // @formatter:on } @Test void parseInvalidClasspathResourceSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-r", "--select-resource"); } @ParameterizedTest @EnumSource void parseValidIterationSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectIteration(selectClasspathResource("/foo.csv"), 0)), type.parseArgLine("-i resource:/foo.csv[0]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectMethod("com.acme.Foo#m()"), 1, 2)), type.parseArgLine("--i method:com.acme.Foo#m()[1..2]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectClass("com.acme.Foo"), 0, 2)), type.parseArgLine("-select-iteration class:com.acme.Foo[0,2]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectPackage("com.acme.foo"), 3)), type.parseArgLine("-select-iteration=package:com.acme.foo[3]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectModule("com.acme.foo"), 0, 1, 2, 4, 5, 6)), type.parseArgLine("--select-iteration module:com.acme.foo[0..2,4..6]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectDirectory("foo/bar"), 1, 5)), type.parseArgLine("--select-iteration=directory:foo/bar[1,5]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectFile("foo.txt"), 6), selectIteration(selectUri("file:///foo.txt"), 7)), type.parseArgLine("-i file:foo.txt[6] -i uri:file:///foo.txt[7]").discovery.getSelectedIterations()) ); // @formatter:on } @Test void parseInvalidIterationSelectors() { assertOptionWithMissingRequiredArgumentThrowsException("-i", "--select-iteration"); } @ParameterizedTest @EnumSource void parseClasspathScanningEntries(ArgsType type) { var dir = Paths.get("."); // @formatter:off assertAll( () -> assertTrue(type.parseArgLine("--scan-class-path").discovery.isScanClasspath()), () -> assertEquals(List.of(), type.parseArgLine("--scan-class-path").discovery.getSelectedClasspathEntries()), () -> assertTrue(type.parseArgLine("--scan-classpath").discovery.isScanClasspath()), () -> assertEquals(List.of(), type.parseArgLine("--scan-classpath").discovery.getSelectedClasspathEntries()), () -> assertTrue(type.parseArgLine("--scan-class-path .").discovery.isScanClasspath()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path .").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path=.").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("-scan-class-path .").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("-scan-class-path=.").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path . --scan-class-path src/test/java").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path ." + File.pathSeparator + "src/test/java").discovery.getSelectedClasspathEntries()) ); // @formatter:on } @ParameterizedTest @EnumSource void parseValidConfigurationParameters(ArgsType type) { // @formatter:off assertAll( () -> assertThat(type.parseArgLine("-config foo=bar").discovery.getConfigurationParameters()) .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("-config=foo=bar").discovery.getConfigurationParameters()) .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("--config foo=bar").discovery.getConfigurationParameters()) .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("--config=foo=bar").discovery.getConfigurationParameters()) .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("--config foo=bar --config baz=qux").discovery.getConfigurationParameters()) .containsExactly(entry("foo", "bar"), entry("baz", "qux")) ); // @formatter:on } @Test void parseInvalidConfigurationParameters() { assertOptionWithMissingRequiredArgumentThrowsException("-config", "--config"); } @ParameterizedTest @EnumSource void parseInvalidConfigurationParametersWithDuplicateKey(ArgsType type) { Exception e = assertThrows(Exception.class, () -> type.parseArgLine("--config foo=bar --config foo=baz")); assertThat(e.getMessage()).isEqualTo("Duplicate key 'foo' for values 'bar' and 'baz'."); } private void assertOptionWithMissingRequiredArgumentThrowsException(String... options) { assertAll( Stream.of(options).map(opt -> () -> assertThrows(Exception.class, () -> ArgsType.args.parseArgLine(opt)))); } enum ArgsType { args { @Override Result parseArgLine(String argLine) { return parse(split(argLine)); } }, atFile { @Override Result parseArgLine(String argLine) throws IOException { var atFile = Files.createTempFile("junit-launcher-args", ".txt"); try { Files.write(atFile, List.of(split(argLine))); return parse("@" + atFile); } finally { Files.deleteIfExists(atFile); } } }; abstract Result parseArgLine(String argLine) throws IOException; private static String[] split(String argLine) { return "".equals(argLine) ? new String[0] : argLine.split("\\s+"); } } private static Result parse(String... args) { ExecuteTestsCommand command = new ExecuteTestsCommand((__, ___) -> null); command.parseArgs(args); return new Result(command.toTestDiscoveryOptions(), command.toTestConsoleOutputOptions()); } record Result(TestDiscoveryOptions discovery, TestConsoleOutputOptions output) { } } ConsoleUtilsTests.java000066400000000000000000000014151455764576500340360ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.charset.Charset; import org.junit.jupiter.api.Test; class ConsoleUtilsTests { @Test void consoleCharsetReportedByConsoleUtilsIsEitherNativeCharsetOrDefaultCharset() { var console = System.console(); var expected = console != null ? console.charset() : Charset.defaultCharset(); assertEquals(expected, ConsoleUtils.charset()); } } ExecuteTestsCommandTests.java000066400000000000000000000056501455764576500353440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/options/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.nio.file.Paths; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.console.tasks.ConsoleTestExecutor; import org.junit.platform.launcher.listeners.TestExecutionSummary; /** * @since 1.10 */ class ExecuteTestsCommandTests { private final TestExecutionSummary summary = mock(); private final ConsoleTestExecutor consoleTestExecutor = mock(); private final ExecuteTestsCommand command = new ExecuteTestsCommand((__, ___) -> consoleTestExecutor); @BeforeEach void setUp() { when(consoleTestExecutor.execute(any(), any())).thenReturn(summary); } @Test void hasStatusCode0ForNoTotalFailures() { when(summary.getTotalFailureCount()).thenReturn(0L); command.execute(); assertThat(command.getExitCode()).isEqualTo(0); } @Test void hasStatusCode1ForForAnyFailure() { when(summary.getTotalFailureCount()).thenReturn(1L); command.execute(); assertThat(command.getExitCode()).isEqualTo(1); } /** * @since 1.3 */ @Test void hasStatusCode2ForNoTestsAndHasOptionFailIfNoTestsFound() { when(summary.getTestsFoundCount()).thenReturn(0L); command.execute("--fail-if-no-tests"); assertThat(command.getExitCode()).isEqualTo(2); } /** * @since 1.3 */ @Test void hasStatusCode0ForTestsAndHasOptionFailIfNoTestsFound() { when(summary.getTestsFoundCount()).thenReturn(1L); when(summary.getTotalFailureCount()).thenReturn(0L); command.execute("--fail-if-no-tests"); assertThat(command.getExitCode()).isEqualTo(0); } /** * @since 1.3 */ @Test void hasStatusCode0ForNoTestsAndNotFailIfNoTestsFound() { when(summary.getTestsFoundCount()).thenReturn(0L); command.execute(); assertThat(command.getExitCode()).isEqualTo(0); } @Test void parseValidXmlReportsDirs() { var dir = Paths.get("build", "test-results"); // @formatter:off assertAll( () -> assertEquals(Optional.empty(), parseArgs().getReportsDir()), () -> assertEquals(Optional.of(dir), parseArgs("--reports-dir", "build/test-results").getReportsDir()), () -> assertEquals(Optional.of(dir), parseArgs("--reports-dir=build/test-results").getReportsDir()) ); // @formatter:on } private ExecuteTestsCommand parseArgs(String... args) { command.parseArgs(args); return command; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/options/ThemeTests.java000066400000000000000000000020521455764576500325320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.options; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; class ThemeTests { @Test void givenUtf8ShouldReturnUnicode() { assertEquals(Theme.UNICODE, Theme.valueOf(StandardCharsets.UTF_8)); } @Test void givenAnythingElseShouldReturnAscii() { assertAll("All character sets that are not UTF-8 should return Theme.ASCII", () -> { assertEquals(Theme.ASCII, Theme.valueOf(StandardCharsets.ISO_8859_1)); assertEquals(Theme.ASCII, Theme.valueOf(StandardCharsets.US_ASCII)); assertEquals(Theme.ASCII, Theme.valueOf(StandardCharsets.UTF_16)); }); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/000077500000000000000000000000001455764576500302155ustar00rootroot00000000000000ContainerForInnerTest.java000066400000000000000000000014231455764576500352260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Test in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class ContainerForInnerTest { @Nested class NestedTest { @Test void test() { } } } ContainerForInnerTests.java000066400000000000000000000014261455764576500354140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Tests in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class ContainerForInnerTests { @Nested class NestedTests { @Test void test() { } } } ContainerForStaticNestedTest.java000066400000000000000000000013631455764576500365500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Test in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class ContainerForStaticNestedTest { static class NestedTest { @Test void test() { } } } ContainerForStaticNestedTests.java000066400000000000000000000013661455764576500367360ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Tests in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class ContainerForStaticNestedTests { static class NestedTests { @Test void test() { } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/SecondTest.java000066400000000000000000000012771455764576500331420ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Test in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class SecondTest { @Test void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/Test.java000066400000000000000000000012521455764576500317770ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named Test in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class Test { @org.junit.jupiter.api.Test void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/Test1.java000066400000000000000000000012721455764576500320620ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named Test* in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class Test1 { @Test void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/Tests.java000066400000000000000000000012721455764576500321640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named Tests in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class Tests { @Test void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/subpackage/ThirdTests.java000066400000000000000000000013001455764576500331470ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.subpackage; import org.junit.jupiter.api.Test; // Even though our "example test classes" should be named *TestCase // according to team policy, this class must be named *Tests in order // for ConsoleLauncherIntegrationTests to pass, but that's not a // problem since the test method here can never fail. class ThirdTests { @Test void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/000077500000000000000000000000001455764576500272355ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/ColorPaletteTests.java000066400000000000000000000137271455764576500335320ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import java.io.PrintWriter; import java.io.StringReader; import java.util.List; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * Unit tests for {@link ColorPalette}. * * @since 1.9 */ class ColorPaletteTests { @Nested class LoadFromPropertiesTests { @Test void singleOverride() { String properties = """ SUCCESSFUL = 35;1 """; ColorPalette colorPalette = new ColorPalette(new StringReader(properties)); String actual = colorPalette.paint(Style.SUCCESSFUL, "text"); assertEquals("\u001B[35;1mtext\u001B[0m", actual); } @Test void keysAreCaseInsensitive() { String properties = """ suCcESSfuL = 35;1 """; ColorPalette colorPalette = new ColorPalette(new StringReader(properties)); String actual = colorPalette.paint(Style.SUCCESSFUL, "text"); assertEquals("\u001B[35;1mtext\u001B[0m", actual); } @Test void junkKeysAreIgnored() { String properties = """ SUCCESSFUL = 35;1 JUNK = 1;31;40 """; ColorPalette colorPalette = new ColorPalette(new StringReader(properties)); String actual = colorPalette.paint(Style.SUCCESSFUL, "text"); assertEquals("\u001B[35;1mtext\u001B[0m", actual); } @Test void multipleOverrides() { String properties = """ SUCCESSFUL = 35;1 FAILED = 33;4 """; ColorPalette colorPalette = new ColorPalette(new StringReader(properties)); String successful = colorPalette.paint(Style.SUCCESSFUL, "text"); String failed = colorPalette.paint(Style.FAILED, "text"); assertEquals("\u001B[35;1mtext\u001B[0m", successful); assertEquals("\u001B[33;4mtext\u001B[0m", failed); } @Test void unspecifiedStylesAreDefault() { String properties = """ SUCCESSFUL = 35;1 """; ColorPalette colorPalette = new ColorPalette(new StringReader(properties)); String actual = colorPalette.paint(Style.FAILED, "text"); assertEquals("\u001B[31mtext\u001B[0m", actual); } @Test void cannotOverrideNone() { String properties = """ NONE = 35;1 """; StringReader reader = new StringReader(properties); assertThrows(IllegalArgumentException.class, () -> new ColorPalette(reader)); } } /** * TODO Actually assert something in these "demo" tests and stop printing to SYSOUT. */ @Nested class DemonstratePalettesTests { @Test void verbose_default() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new VerboseTreePrintingListener(out, ColorPalette.DEFAULT, 16, Theme.ASCII); demoTestRun(listener); assertDoesNotThrow(out::flush); } @Test void verbose_single_color() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new VerboseTreePrintingListener(out, ColorPalette.SINGLE_COLOR, 16, Theme.ASCII); demoTestRun(listener); assertDoesNotThrow(out::flush); } @Test void simple_default() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new TreePrintingListener(out, ColorPalette.DEFAULT, Theme.ASCII); demoTestRun(listener); assertDoesNotThrow(out::flush); } @Test void simple_single_color() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new TreePrintingListener(out, ColorPalette.SINGLE_COLOR, Theme.ASCII); demoTestRun(listener); assertDoesNotThrow(out::flush); } @Test void flat_default() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new FlatPrintingListener(out, ColorPalette.DEFAULT); demoTestRun(listener); assertDoesNotThrow(out::flush); } @Test void flat_single_color() { PrintWriter out = new PrintWriter(System.out); TestExecutionListener listener = new FlatPrintingListener(out, ColorPalette.SINGLE_COLOR); demoTestRun(listener); assertDoesNotThrow(out::flush); } private void demoTestRun(TestExecutionListener listener) { TestDescriptor testDescriptor = new TestDescriptorStub(UniqueId.forEngine("demo-engine"), "My Test"); TestPlan testPlan = TestPlan.from(List.of(testDescriptor), mock()); listener.testPlanExecutionStarted(testPlan); listener.executionStarted(TestIdentifier.from(testDescriptor)); listener.executionFinished(TestIdentifier.from(testDescriptor), TestExecutionResult.successful()); listener.dynamicTestRegistered(TestIdentifier.from(testDescriptor)); listener.executionStarted(TestIdentifier.from(testDescriptor)); listener.executionFinished(TestIdentifier.from(testDescriptor), TestExecutionResult.failed(new Exception())); listener.executionStarted(TestIdentifier.from(testDescriptor)); listener.executionFinished(TestIdentifier.from(testDescriptor), TestExecutionResult.aborted(new Exception())); listener.reportingEntryPublished(TestIdentifier.from(testDescriptor), ReportEntry.from("Key", "Value")); listener.executionSkipped(TestIdentifier.from(testDescriptor), "to demonstrate skipping"); listener.testPlanExecutionFinished(testPlan); } } } ConsoleTestExecutorTests.java000066400000000000000000000113121455764576500350230ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.commons.util.ClassLoaderUtils.getDefaultClassLoader; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Paths; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.platform.console.options.Details; import org.junit.platform.console.options.TestConsoleOutputOptions; import org.junit.platform.console.options.TestDiscoveryOptions; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; /** * @since 1.0 */ class ConsoleTestExecutorTests { private static final Runnable FAILING_BLOCK = () -> fail("should fail"); private static final Runnable SUCCEEDING_TEST = () -> { }; private final StringWriter stringWriter = new StringWriter(); private final TestDiscoveryOptions discoveryOptions = new TestDiscoveryOptions(); private final TestConsoleOutputOptions outputOptions = new TestConsoleOutputOptions(); private final DemoHierarchicalTestEngine dummyTestEngine = new DemoHierarchicalTestEngine(); { discoveryOptions.setScanClasspath(true); } @Test void printsSummary() { dummyTestEngine.addTest("succeedingTest", SUCCEEDING_TEST); dummyTestEngine.addTest("failingTest", FAILING_BLOCK); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).contains("Test run finished after", "2 tests found", "0 tests skipped", "2 tests started", "0 tests aborted", "1 tests successful", "1 tests failed"); } @Test void printsDetailsIfTheyAreNotHidden() { outputOptions.setDetails(Details.FLAT); dummyTestEngine.addTest("failingTest", FAILING_BLOCK); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).contains("Test execution started."); } @Test void printsNoDetailsIfTheyAreHidden() { outputOptions.setDetails(Details.NONE); dummyTestEngine.addTest("failingTest", FAILING_BLOCK); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).doesNotContain("Test execution started."); } @Test void printsFailuresEvenIfDetailsAreHidden() { outputOptions.setDetails(Details.NONE); dummyTestEngine.addTest("failingTest", FAILING_BLOCK); dummyTestEngine.addContainer("failingContainer", FAILING_BLOCK); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).contains("Failures (2)", "failingTest", "failingContainer"); } @Test void usesCustomClassLoaderIfAdditionalClassPathEntriesArePresent() { discoveryOptions.setAdditionalClasspathEntries(List.of(Paths.get("."))); var oldClassLoader = getDefaultClassLoader(); dummyTestEngine.addTest("failingTest", () -> assertSame(oldClassLoader, getDefaultClassLoader(), "should fail")); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).contains("failingTest", "should fail", "1 tests failed"); } @Test void usesSameClassLoaderIfNoAdditionalClassPathEntriesArePresent() { discoveryOptions.setAdditionalClasspathEntries(List.of()); var oldClassLoader = getDefaultClassLoader(); dummyTestEngine.addTest("failingTest", () -> assertNotSame(oldClassLoader, getDefaultClassLoader(), "should fail")); var task = new ConsoleTestExecutor(discoveryOptions, outputOptions, () -> createLauncher(dummyTestEngine)); task.execute(new PrintWriter(stringWriter), Optional.empty()); assertThat(stringWriter.toString()).contains("failingTest", "should fail", "1 tests failed"); } } CustomContextClassLoaderExecutorTests.java000066400000000000000000000045201455764576500375200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; /** * @since 1.0 */ class CustomContextClassLoaderExecutorTests { @Test void invokeWithoutCustomClassLoaderDoesNotSetClassLoader() throws Exception { var originalClassLoader = Thread.currentThread().getContextClassLoader(); var executor = new CustomContextClassLoaderExecutor(Optional.empty()); int result = executor.invoke(() -> { assertSame(originalClassLoader, Thread.currentThread().getContextClassLoader()); return 42; }); assertEquals(42, result); assertSame(originalClassLoader, Thread.currentThread().getContextClassLoader()); } @Test void invokeWithCustomClassLoaderSetsCustomAndResetsToOriginal() throws Exception { var originalClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader customClassLoader = URLClassLoader.newInstance(new URL[0]); var executor = new CustomContextClassLoaderExecutor(Optional.of(customClassLoader)); int result = executor.invoke(() -> { assertSame(customClassLoader, Thread.currentThread().getContextClassLoader()); return 23; }); assertEquals(23, result); assertSame(originalClassLoader, Thread.currentThread().getContextClassLoader()); } @Test void invokeWithCustomClassLoaderAndEnsureItIsClosedAfterUsage() throws Exception { var closed = new AtomicBoolean(false); ClassLoader localClassLoader = new URLClassLoader(new URL[0]) { @Override public void close() throws IOException { closed.set(true); super.close(); } }; var executor = new CustomContextClassLoaderExecutor(Optional.of(localClassLoader)); int result = executor.invoke(() -> 4711); assertEquals(4711, result); assertTrue(closed.get()); } } DiscoveryRequestCreatorTests.java000066400000000000000000000306431455764576500357120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static java.util.stream.Collectors.toMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathResource; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectFile; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; import java.io.File; import java.net.URI; import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.console.options.TestDiscoveryOptions; import org.junit.platform.engine.Filter; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.ClasspathRootSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.IterationSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * @since 1.0 */ class DiscoveryRequestCreatorTests { private final TestDiscoveryOptions options = new TestDiscoveryOptions(); @Test void convertsScanClasspathOptionWithoutExplicitRootDirectories() { options.setScanClasspath(true); var request = convert(); var classpathRootSelectors = request.getSelectorsByType(ClasspathRootSelector.class); // @formatter:off assertThat(classpathRootSelectors).extracting(ClasspathRootSelector::getClasspathRoot) .hasAtLeastOneElementOfType(URI.class) .doesNotContainNull(); // @formatter:on } @Test void convertsScanClasspathOptionWithExplicitRootDirectories() { options.setScanClasspath(true); options.setSelectedClasspathEntries(List.of(Paths.get("."), Paths.get(".."))); var request = convert(); var classpathRootSelectors = request.getSelectorsByType(ClasspathRootSelector.class); // @formatter:off assertThat(classpathRootSelectors).extracting(ClasspathRootSelector::getClasspathRoot) .containsExactly(new File(".").toURI(), new File("..").toURI()); // @formatter:on } @Test void convertsScanClasspathOptionWithAdditionalClasspathEntries() { options.setScanClasspath(true); options.setAdditionalClasspathEntries(List.of(Paths.get("."), Paths.get(".."))); var request = convert(); var classpathRootSelectors = request.getSelectorsByType(ClasspathRootSelector.class); // @formatter:off assertThat(classpathRootSelectors).extracting(ClasspathRootSelector::getClasspathRoot) .contains(new File(".").toURI(), new File("..").toURI()); // @formatter:on } @Test void doesNotSupportScanClasspathAndExplicitSelectors() { options.setScanClasspath(true); options.setSelectedClasses(List.of(selectClass("SomeTest"))); Throwable cause = assertThrows(PreconditionViolationException.class, this::convert); assertThat(cause).hasMessageContaining("not supported"); } @Test void convertsDefaultIncludeClassNamePatternOption() { options.setScanClasspath(true); var request = convert(); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).hasSize(1); assertExcludes(filters.get(0), STANDARD_INCLUDE_PATTERN); } @Test void convertsExplicitIncludeClassNamePatternOption() { options.setScanClasspath(true); options.setIncludedClassNamePatterns(List.of("Foo.*Bar", "Bar.*Foo")); var request = convert(); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).hasSize(1); assertIncludes(filters.get(0), "Foo.*Bar"); assertIncludes(filters.get(0), "Bar.*Foo"); } @Test void includeSelectedClassesAndMethodsRegardlessOfClassNamePatterns() { options.setSelectedClasses(List.of(selectClass("SomeTest"))); options.setSelectedMethods(List.of(selectMethod("com.acme.Foo#m()"))); options.setSelectedIterations(List.of(selectIteration(selectMethod("com.acme.Bar#n()"), 0))); options.setIncludedClassNamePatterns(List.of("Foo.*Bar")); var request = convert(); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).hasSize(1); assertIncludes(filters.get(0), "SomeTest"); assertIncludes(filters.get(0), "com.acme.Foo"); assertIncludes(filters.get(0), "com.acme.Bar"); assertIncludes(filters.get(0), "Foo.*Bar"); } @Test void convertsExcludeClassNamePatternOption() { options.setScanClasspath(true); options.setExcludedClassNamePatterns(List.of("Foo.*Bar", "Bar.*Foo")); var request = convert(); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).hasSize(2); assertExcludes(filters.get(1), "Foo.*Bar"); assertExcludes(filters.get(1), "Bar.*Foo"); } @Test void convertsPackageOptions() { options.setScanClasspath(true); options.setIncludedPackages(List.of("org.junit.included1", "org.junit.included2", "org.junit.included3")); options.setExcludedPackages(List.of("org.junit.excluded1")); var request = convert(); var packageNameFilters = request.getFiltersByType(PackageNameFilter.class); assertThat(packageNameFilters).hasSize(2); assertIncludes(packageNameFilters.get(0), "org.junit.included1"); assertIncludes(packageNameFilters.get(0), "org.junit.included2"); assertIncludes(packageNameFilters.get(0), "org.junit.included3"); assertExcludes(packageNameFilters.get(1), "org.junit.excluded1"); } @Test void convertsTagOptions() { options.setScanClasspath(true); options.setIncludedTagExpressions(List.of("fast", "medium", "slow")); options.setExcludedTagExpressions(List.of("slow")); var request = convert(); var postDiscoveryFilters = request.getPostDiscoveryFilters(); assertThat(postDiscoveryFilters).hasSize(2); assertThat(postDiscoveryFilters.get(0).toString()).contains("TagFilter"); assertThat(postDiscoveryFilters.get(1).toString()).contains("TagFilter"); } @Test void convertsEngineOptions() { options.setScanClasspath(true); options.setIncludedEngines(List.of("engine1", "engine2", "engine3")); options.setExcludedEngines(List.of("engine2")); var request = convert(); var engineFilters = request.getEngineFilters(); assertThat(engineFilters).hasSize(2); assertThat(engineFilters.get(0).toString()).contains("includes", "[engine1, engine2, engine3]"); assertThat(engineFilters.get(1).toString()).contains("excludes", "[engine2]"); } @Test void propagatesUriSelectors() { options.setSelectedUris(List.of(selectUri("a"), selectUri("b"))); var request = convert(); var uriSelectors = request.getSelectorsByType(UriSelector.class); assertThat(uriSelectors).extracting(UriSelector::getUri).containsExactly(URI.create("a"), URI.create("b")); } @Test void propagatesFileSelectors() { options.setSelectedFiles(List.of(selectFile("foo.txt"), selectFile("bar.csv"))); var request = convert(); var fileSelectors = request.getSelectorsByType(FileSelector.class); assertThat(fileSelectors).extracting(FileSelector::getRawPath).containsExactly("foo.txt", "bar.csv"); } @Test void propagatesDirectorySelectors() { options.setSelectedDirectories(List.of(selectDirectory("foo/bar"), selectDirectory("bar/qux"))); var request = convert(); var directorySelectors = request.getSelectorsByType(DirectorySelector.class); assertThat(directorySelectors).extracting(DirectorySelector::getRawPath).containsExactly("foo/bar", "bar/qux"); } @Test void propagatesPackageSelectors() { options.setSelectedPackages(List.of(selectPackage("com.acme.foo"), selectPackage("com.example.bar"))); var request = convert(); var packageSelectors = request.getSelectorsByType(PackageSelector.class); assertThat(packageSelectors).extracting(PackageSelector::getPackageName).containsExactly("com.acme.foo", "com.example.bar"); } @Test void propagatesClassSelectors() { options.setSelectedClasses(List.of(selectClass("com.acme.Foo"), selectClass("com.example.Bar"))); var request = convert(); var classSelectors = request.getSelectorsByType(ClassSelector.class); assertThat(classSelectors).extracting(ClassSelector::getClassName).containsExactly("com.acme.Foo", "com.example.Bar"); } @Test void propagatesMethodSelectors() { options.setSelectedMethods( List.of(selectMethod("com.acme.Foo#m()"), selectMethod("com.example.Bar#method(java.lang.Object)"))); var request = convert(); var methodSelectors = request.getSelectorsByType(MethodSelector.class); assertThat(methodSelectors).hasSize(2); assertThat(methodSelectors.get(0).getClassName()).isEqualTo("com.acme.Foo"); assertThat(methodSelectors.get(0).getMethodName()).isEqualTo("m"); assertThat(methodSelectors.get(0).getParameterTypeNames()).isEmpty(); assertThat(methodSelectors.get(1).getClassName()).isEqualTo("com.example.Bar"); assertThat(methodSelectors.get(1).getMethodName()).isEqualTo("method"); assertThat(methodSelectors.get(1).getParameterTypeNames()).isEqualTo("java.lang.Object"); } @Test void propagatesClasspathResourceSelectors() { options.setSelectedClasspathResources( List.of(selectClasspathResource("foo.csv"), selectClasspathResource("com/example/bar.json"))); var request = convert(); var classpathResourceSelectors = request.getSelectorsByType(ClasspathResourceSelector.class); assertThat(classpathResourceSelectors).extracting( ClasspathResourceSelector::getClasspathResourceName).containsExactly("foo.csv", "com/example/bar.json"); } @Test void propagatesIterationSelectors() { var methodSelector = selectMethod("com.acme.Foo#m()"); var classSelector = selectClass("com.example.Bar"); options.setSelectedIterations(List.of(selectIteration(methodSelector, 1), selectIteration(classSelector, 2))); var request = convert(); var iterationSelectors = request.getSelectorsByType(IterationSelector.class); assertThat(iterationSelectors).hasSize(2); assertThat(iterationSelectors.get(0).getParentSelector()).isEqualTo(methodSelector); assertThat(iterationSelectors.get(0).getIterationIndices()).containsExactly(1); assertThat(iterationSelectors.get(1).getParentSelector()).isEqualTo(classSelector); assertThat(iterationSelectors.get(1).getIterationIndices()).containsExactly(2); } @Test @SuppressWarnings("deprecation") void convertsConfigurationParameters() { options.setScanClasspath(true); options.setConfigurationParameters(mapOf(entry("foo", "bar"), entry("baz", "true"))); var request = convert(); var configurationParameters = request.getConfigurationParameters(); assertThat(configurationParameters.size()).isEqualTo(2); assertThat(configurationParameters.get("foo")).contains("bar"); assertThat(configurationParameters.getBoolean("baz")).contains(true); } private LauncherDiscoveryRequest convert() { var creator = new DiscoveryRequestCreator(); return creator.toDiscoveryRequest(options); } private void assertIncludes(Filter filter, String included) { assertThat(filter.apply(included).included()).isTrue(); } private void assertExcludes(Filter filter, String excluded) { assertThat(filter.apply(excluded).excluded()).isTrue(); } @SafeVarargs @SuppressWarnings("varargs") private static Map mapOf(Entry... entries) { return Stream.of(entries).collect(toMap(Entry::getKey, Entry::getValue)); } } FlatPrintingListenerTests.java000066400000000000000000000147131455764576500351610ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.console.tasks.FlatPrintingListener.INDENTATION; import static org.junit.platform.engine.TestExecutionResult.failed; import java.io.PrintWriter; import java.io.StringWriter; import org.assertj.core.util.Maps; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; /** * @since 1.0 */ class FlatPrintingListenerTests { private static final String EOL = System.lineSeparator(); @Test void executionSkipped() { var stringWriter = new StringWriter(); listener(stringWriter).executionSkipped(newTestIdentifier(), "Test" + EOL + "disabled"); var lines = lines(stringWriter); assertEquals(3, lines.length); assertAll("lines in the output", // () -> assertEquals("Skipped: demo-test ([engine:demo-engine])", lines[0]), // () -> assertEquals(INDENTATION + "=> Reason: Test", lines[1]), // () -> assertEquals(INDENTATION + "disabled", lines[2])); } @Test void reportingEntryPublished() { var stringWriter = new StringWriter(); listener(stringWriter).reportingEntryPublished(newTestIdentifier(), ReportEntry.from("foo", "bar")); var lines = lines(stringWriter); assertEquals(2, lines.length); assertAll("lines in the output", // () -> assertEquals("Reported: demo-test ([engine:demo-engine])", lines[0]), // () -> assertTrue(lines[1].startsWith(INDENTATION + "=> Reported values: ReportEntry [timestamp =")), // () -> assertTrue(lines[1].endsWith(", foo = 'bar']"))); } @Test void executionFinishedWithFailure() { var stringWriter = new StringWriter(); listener(stringWriter).executionFinished(newTestIdentifier(), failed(new AssertionError("Boom!"))); var lines = lines(stringWriter); assertAll("lines in the output", // () -> assertEquals("Finished: demo-test ([engine:demo-engine])", lines[0]), // () -> assertEquals(INDENTATION + "=> Exception: java.lang.AssertionError: Boom!", lines[1])); } @Nested class ColorPaletteTests { @Nested class DefaultColorPaletteTests { @Test void executionSkipped() { var stringWriter = new StringWriter(); new FlatPrintingListener(new PrintWriter(stringWriter), ColorPalette.DEFAULT).executionSkipped( newTestIdentifier(), "Test" + EOL + "disabled"); var lines = lines(stringWriter); assertEquals(3, lines.length); assertAll("lines in the output", // () -> assertEquals("\u001B[35mSkipped: demo-test ([engine:demo-engine])\u001B[0m", lines[0]), // () -> assertEquals("\u001B[35m" + INDENTATION + "=> Reason: Test", lines[1]), // () -> assertEquals(INDENTATION + "disabled\u001B[0m", lines[2])); } @Test void reportingEntryPublished() { var stringWriter = new StringWriter(); new FlatPrintingListener(new PrintWriter(stringWriter), ColorPalette.DEFAULT).reportingEntryPublished( newTestIdentifier(), ReportEntry.from("foo", "bar")); var lines = lines(stringWriter); assertEquals(2, lines.length); assertAll("lines in the output", // () -> assertEquals("\u001B[37mReported: demo-test ([engine:demo-engine])\u001B[0m", lines[0]), // () -> assertTrue(lines[1].startsWith( "\u001B[37m" + INDENTATION + "=> Reported values: ReportEntry [timestamp =")), // () -> assertTrue(lines[1].endsWith(", foo = 'bar']\u001B[0m"))); } @Test void executionFinishedWithFailure() { var stringWriter = new StringWriter(); new FlatPrintingListener(new PrintWriter(stringWriter), ColorPalette.DEFAULT).executionFinished( newTestIdentifier(), failed(new AssertionError("Boom!"))); var lines = lines(stringWriter); assertAll("lines in the output", // () -> assertEquals("\u001B[31mFinished: demo-test ([engine:demo-engine])\u001B[0m", lines[0]), // () -> assertEquals("\u001B[31m" + INDENTATION + "=> Exception: java.lang.AssertionError: Boom!", lines[1]), () -> assertTrue(lines[lines.length - 1].endsWith("\u001B[0m"))); } } @Nested class ColorPaletteOverrideTests { @Test void overridingSkipped() { var stringWriter = new StringWriter(); ColorPalette colorPalette = new ColorPalette(Maps.newHashMap(Style.SKIPPED, "36;7")); new FlatPrintingListener(new PrintWriter(stringWriter), colorPalette).executionSkipped( newTestIdentifier(), "Test" + EOL + "disabled"); var lines = lines(stringWriter); assertEquals(3, lines.length); assertAll("lines in the output", // () -> assertEquals("\u001B[36;7mSkipped: demo-test ([engine:demo-engine])\u001B[0m", lines[0]), // () -> assertEquals("\u001B[36;7m" + INDENTATION + "=> Reason: Test", lines[1]), // () -> assertEquals(INDENTATION + "disabled\u001B[0m", lines[2])); } @Test void overridingUnusedStyle() { var stringWriter = new StringWriter(); ColorPalette colorPalette = new ColorPalette(Maps.newHashMap(Style.FAILED, "36;7")); new FlatPrintingListener(new PrintWriter(stringWriter), colorPalette).executionSkipped( newTestIdentifier(), "Test" + EOL + "disabled"); var lines = lines(stringWriter); assertEquals(3, lines.length); assertAll("lines in the output", // () -> assertEquals("\u001B[35mSkipped: demo-test ([engine:demo-engine])\u001B[0m", lines[0]), // () -> assertEquals("\u001B[35m" + INDENTATION + "=> Reason: Test", lines[1]), // () -> assertEquals(INDENTATION + "disabled\u001B[0m", lines[2])); } } } private FlatPrintingListener listener(StringWriter stringWriter) { return new FlatPrintingListener(new PrintWriter(stringWriter), ColorPalette.NONE); } private static TestIdentifier newTestIdentifier() { var testDescriptor = new TestDescriptorStub(UniqueId.forEngine("demo-engine"), "demo-test"); return TestIdentifier.from(testDescriptor); } private String[] lines(StringWriter stringWriter) { return stringWriter.toString().split(EOL); } } TestFeedPrintingListenerTests.java000066400000000000000000000066161455764576500360010ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.mockito.Mockito.mock; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collections; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.opentest4j.TestAbortedException; public class TestFeedPrintingListenerTests { TestPlan testPlan; TestIdentifier testIdentifier; StringWriter stringWriter = new StringWriter(); TestFeedPrintingListener listener = new TestFeedPrintingListener(new PrintWriter(stringWriter), ColorPalette.NONE); @BeforeEach void prepareListener() { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("demo-engine"), "Demo Engine"); var testDescriptor = new TestDescriptorStub(engineDescriptor.getUniqueId().append("type", "test"), "%c ool test"); engineDescriptor.addChild(testDescriptor); testPlan = TestPlan.from(Collections.singleton(engineDescriptor), mock()); testIdentifier = testPlan.getTestIdentifier(testDescriptor.getUniqueId()); listener.testPlanExecutionStarted(testPlan); } @Test public void testExecutionSkipped() { listener.executionSkipped(testIdentifier, "Test disabled"); assertLinesMatch( // """ Demo Engine > %c ool test :: SKIPPED \tReason: Test disabled """.lines(), // actualLines() // ); } @Test public void testExecutionFailed() { listener.executionFinished(testIdentifier, TestExecutionResult.failed(new AssertionError("Boom!"))); assertLinesMatch( // """ Demo Engine > %c ool test :: FAILED \tjava.lang.AssertionError: Boom! >>>> """.lines(), // actualLines() // ); } @Test public void testExecutionAborted() { listener.executionFinished(testIdentifier, TestExecutionResult.aborted(new TestAbortedException("Boom!"))); assertLinesMatch( // """ Demo Engine > %c ool test :: ABORTED \torg.opentest4j.TestAbortedException: Boom! >>>> """.lines(), // actualLines() // ); } @Test public void testExecutionSucceeded() { listener.executionFinished(testIdentifier, TestExecutionResult.successful()); assertLinesMatch(Stream.of("Demo Engine > %c ool test :: SUCCESSFUL"), actualLines()); } @Test public void testExecutionFailedOfContainer() { var engineIdentifier = getOnlyElement(testPlan.getRoots()); listener.executionFinished(engineIdentifier, TestExecutionResult.failed(new AssertionError("Boom!"))); assertLinesMatch( // """ Demo Engine :: FAILED \tjava.lang.AssertionError: Boom! >>>> """.lines(), // actualLines() // ); } private Stream actualLines() { return stringWriter.toString().lines(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/TreeNodeTests.java000066400000000000000000000056151455764576500326370ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import org.junit.jupiter.api.Test; import org.junit.platform.engine.reporting.ReportEntry; class TreeNodeTests { private static final int NUM_THREADS = 2; private static final int ITEMS_PER_THREAD = 1000; @Test void caption() { assertEquals("", TreeNode.createCaption("")); assertEquals("[@@]", TreeNode.createCaption("[@@]")); assertEquals("[@ @]", TreeNode.createCaption("[@ @]")); assertEquals("[@ @]", TreeNode.createCaption("[@\u000B@]")); assertEquals("[@ @]", TreeNode.createCaption("[@\t@]")); assertEquals("[@ @]", TreeNode.createCaption("[@\t\n@]")); assertEquals("[@ @]", TreeNode.createCaption("[@\t\n\r@]")); assertEquals("[@ @]", TreeNode.createCaption("[@\t\n\r\f@]")); assertEquals("@".repeat(80) + "...", TreeNode.createCaption("@".repeat(1000) + "!")); } @Test void childrenCanBeAddedConcurrently() throws Exception { var treeNode = new TreeNode("root"); runConcurrently(() -> { for (long i = 0; i < ITEMS_PER_THREAD; i++) { treeNode.addChild(new TreeNode(String.valueOf(i))); } }); assertThat(treeNode.children).hasSize(NUM_THREADS * ITEMS_PER_THREAD); } @Test void reportEntriesCanBeAddedConcurrently() throws Exception { var treeNode = new TreeNode("root"); runConcurrently(() -> { for (long i = 0; i < ITEMS_PER_THREAD; i++) { treeNode.addReportEntry(ReportEntry.from("index", String.valueOf(i))); } }); assertThat(treeNode.reports).hasSize(NUM_THREADS * ITEMS_PER_THREAD); } private void runConcurrently(Runnable action) throws InterruptedException { ExecutorService executor = new ThreadPoolExecutor(NUM_THREADS, NUM_THREADS, 10, SECONDS, new ArrayBlockingQueue<>(NUM_THREADS)); try { var barrier = new CyclicBarrier(NUM_THREADS); for (long i = 0; i < NUM_THREADS; i++) { executor.submit(() -> { await(barrier); action.run(); }); } } finally { executor.shutdown(); var terminated = executor.awaitTermination(10, SECONDS); assertTrue(terminated, "Executor was not terminated"); } } private void await(CyclicBarrier barrier) { try { barrier.await(); } catch (Exception e) { throw new RuntimeException(e); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/TreePrinterTests.java000066400000000000000000000106521455764576500333720ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.platform.engine.TestExecutionResult.aborted; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; class TreePrinterTests { private final Charset charset = StandardCharsets.UTF_8; private final ByteArrayOutputStream stream = new ByteArrayOutputStream(1000); private final PrintWriter out = new PrintWriter(new OutputStreamWriter(stream, charset)); private List actual() { try { out.flush(); return List.of(stream.toString(charset.name()).split("\\R")); } catch (UnsupportedEncodingException e) { throw new AssertionError(charset.name() + " is an unsupported encoding?!", e); } } @Test void emptyTree() { new TreePrinter(out, Theme.UNICODE, ColorPalette.NONE).print(new TreeNode("")); assertIterableEquals(List.of("╷"), actual()); } @Test void emptyEngines() { var root = new TreeNode(""); root.addChild(new TreeNode(identifier("e-0", "engine zero"), "none")); root.addChild(new TreeNode(identifier("e-1", "engine one")).setResult(successful())); root.addChild(new TreeNode(identifier("e-2", "engine two")).setResult(failed(null))); root.addChild(new TreeNode(identifier("e-3", "engine three")).setResult(aborted(null))); new TreePrinter(out, Theme.UNICODE, ColorPalette.NONE).print(root); assertIterableEquals( // List.of( // "╷", // "├─ engine zero ↷ none", // "├─ engine one ✔", // "├─ engine two ✘", // "└─ engine three ■"), // actual()); } @Test // https://github.com/junit-team/junit5/issues/786 void printNodeHandlesNullMessageThrowableGracefully() { var result = TestExecutionResult.failed(new NullPointerException()); var node = new TreeNode(identifier("NPE", "test()")).setResult(result); new TreePrinter(out, Theme.ASCII, ColorPalette.NONE).print(node); assertLinesMatch(List.of(".", "+-- test() [X] java.lang.NullPointerException"), actual()); } @Test // https://github.com/junit-team/junit5/issues/1531 void reportsAreTabbedCorrectly() { var root = new TreeNode(""); var e1 = new TreeNode(identifier("e-1", "engine one")).setResult(successful()); e1.addReportEntry(ReportEntry.from("key", "e-1")); root.addChild(e1); var c1 = new TreeNode(identifier("c-1", "class one")).setResult(successful()); c1.addReportEntry(ReportEntry.from("key", "c-1")); e1.addChild(c1); var m1 = new TreeNode(identifier("m-1", "method one")).setResult(successful()); m1.addReportEntry(ReportEntry.from("key", "m-1")); c1.addChild(m1); var m2 = new TreeNode(identifier("m-2", "method two")).setResult(successful()); m2.addReportEntry(ReportEntry.from("key", "m-2")); c1.addChild(m2); new TreePrinter(out, Theme.UNICODE, ColorPalette.NONE).print(root); assertLinesMatch(List.of( // "╷", // "└─ engine one ✔", // " │ ....-..-..T..:...* key = `e-1`", // " └─ class one ✔", // " │ ....-..-..T..:...* key = `c-1`", // " ├─ method one ✔", // " │ ....-..-..T..:...* key = `m-1`", // " └─ method two ✔", // " ....-..-..T..:...* key = `m-2`" // ), // actual()); } private static TestIdentifier identifier(String id, String displayName) { var descriptor = new TestDescriptorStub(UniqueId.forEngine(id), displayName); return TestIdentifier.from(descriptor); } } VerboseTreeListenerTests.java000066400000000000000000000057751455764576500350150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/console/tasks/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.console.tasks; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.platform.engine.TestExecutionResult.failed; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; /** * @since 1.3.2 */ class VerboseTreeListenerTests { private static final String EOL = System.lineSeparator(); @Test void executionSkipped() { var stringWriter = new StringWriter(); listener(stringWriter).executionSkipped(newTestIdentifier(), "Test" + EOL + "disabled"); var lines = lines(stringWriter); assertLinesMatch(List.of( // "+-- %c ool test", // " tags: []", // " uniqueId: [engine:demo-engine]", // " parent: []", // " reason: Test", // " disabled", // " status: [S] SKIPPED"), List.of(lines)); } @Test void reportingEntryPublished() { var stringWriter = new StringWriter(); listener(stringWriter).reportingEntryPublished(newTestIdentifier(), ReportEntry.from("foo", "bar")); var lines = lines(stringWriter); assertLinesMatch(List.of(" reports: ReportEntry \\[timestamp = .+, foo = 'bar'\\]"), List.of(lines)); } @Test void executionFinishedWithFailure() { var stringWriter = new StringWriter(); listener(stringWriter).executionFinished(newTestIdentifier(), failed(new AssertionError("Boom!"))); var lines = lines(stringWriter); assertLinesMatch(List.of(" caught: java.lang.AssertionError: Boom!", // ">> STACKTRACE >>", // " duration: \\d+ ms", // " status: [X] FAILED"), List.of(lines)); } @Test void failureMessageWithFormatSpecifier() { var stringWriter = new StringWriter(); listener(stringWriter).executionFinished(newTestIdentifier(), failed(new AssertionError("%crash"))); var lines = lines(stringWriter); assertLinesMatch(List.of(" caught: java.lang.AssertionError: %crash", // ">> STACKTRACE >>", // " duration: \\d+ ms", // " status: [X] FAILED"), List.of(lines)); } private VerboseTreePrintingListener listener(StringWriter stringWriter) { return new VerboseTreePrintingListener(new PrintWriter(stringWriter), ColorPalette.NONE, 16, Theme.ASCII); } private static TestIdentifier newTestIdentifier() { var testDescriptor = new TestDescriptorStub(UniqueId.forEngine("demo-engine"), "%c ool test"); return TestIdentifier.from(testDescriptor); } private String[] lines(StringWriter stringWriter) { return stringWriter.toString().split(EOL); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/000077500000000000000000000000001455764576500257135ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/FilterCompositionTests.java000066400000000000000000000051671455764576500332630ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.FilterResult.included; import org.junit.jupiter.api.Test; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.launcher.FilterStub; /** * Unit tests for {@link Filter#composeFilters}. * * {@link Filter#composeFilters} will delegate to {@linkplain CompositeFilter} under the hood. * * @since 1.0 */ class FilterCompositionTests { @Test void composingNoFiltersCreatesFilterThatIncludesEverything() { var composedFilter = Filter.composeFilters(); assertTrue(composedFilter.apply(String.class).included()); assertTrue(composedFilter.toPredicate().test(String.class)); assertTrue(composedFilter.apply(Object.class).included()); assertTrue(composedFilter.toPredicate().test(Object.class)); } @Test void composingSingleFilterWillReturnTheOriginalOne() { Filter singleFilter = ClassNameFilter.includeClassNamePatterns(".*ring.*"); var composed = Filter.composeFilters(singleFilter); assertSame(singleFilter, composed); } @Test void composingMultipleFiltersIsAConjunctionOfFilters() { Filter firstFilter = ClassNameFilter.includeClassNamePatterns(".*ring.*"); Filter secondFilter = ClassNameFilter.includeClassNamePatterns(".*Join.*"); var composed = Filter.composeFilters(firstFilter, secondFilter); assertFalse(composed.apply("java.lang.String").included()); assertFalse(composed.toPredicate().test("java.lang.String")); assertTrue(composed.apply("java.util.StringJoiner").included()); assertTrue(composed.toPredicate().test("java.util.StringJoiner")); } @Test void aFilterComposedOfMultipleFiltersHasReadableDescription() { Filter firstFilter = new FilterStub<>(o -> excluded("wrong"), () -> "1st"); Filter secondFilter = new FilterStub<>(o -> included("right"), () -> "2nd"); var composed = Filter.composeFilters(firstFilter, secondFilter); assertFalse(composed.apply(String.class).included()); assertEquals("(1st) and (2nd)", composed.toString()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/TestDescriptorTests.java000066400000000000000000000017601455764576500325630ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.fakes.TestDescriptorStub; /** * @since 1.0 */ class TestDescriptorTests { @Test void isRootWithoutParent() { TestDescriptor root = new TestDescriptorStub(UniqueId.root("root", "id"), "id"); assertTrue(root.isRoot()); } @Test void isRootWithParent() { TestDescriptor child = new TestDescriptorStub(UniqueId.root("child", "child"), "child"); child.setParent(new TestDescriptorStub(UniqueId.root("root", "root"), "root")); assertFalse(child.isRoot()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java000066400000000000000000000063441455764576500311630ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link TestTag}. * * @since 1.0 */ class TestTagTests { @Test void validSyntax() { // @formatter:off assertAll("Valid Tag Syntax", () -> yep("fast"), () -> yep("super_fast"), () -> yep("unit-test"), () -> yep("integration.test"), () -> yep("org.example.CustomTagClass"), () -> yep(" surrounded-by-whitespace\t\n"), () -> nope(null), () -> nope(""), () -> nope(" "), () -> nope("\t"), () -> nope("\f"), () -> nope("\r"), () -> nope("\n"), () -> nope("custom tag"), // internal space () -> nope(","), // comma () -> nope("("), // opening parenthesis () -> nope(")"), // closing parenthesis () -> nope("&"), // boolean AND () -> nope("|"), // boolean OR () -> nope("!") // boolean NOT ); // @formatter:on } @Test void factory() { assertEquals("foo", TestTag.create("foo").getName()); assertEquals("foo.tag", TestTag.create("foo.tag").getName()); assertEquals("foo-tag", TestTag.create("foo-tag").getName()); assertEquals("foo-tag", TestTag.create(" foo-tag ").getName()); assertEquals("foo-tag", TestTag.create("\t foo-tag \n").getName()); } @Test void factoryPreconditions() { assertSyntaxViolation(null); assertSyntaxViolation(""); assertSyntaxViolation(" "); assertSyntaxViolation("X\tX"); assertSyntaxViolation("X\nX"); assertSyntaxViolation("XXX\u005CtXXX"); } @Test void tagEqualsOtherTagWithSameName() { assertEquals(TestTag.create("fast"), TestTag.create("fast")); assertEquals(TestTag.create("fast").hashCode(), TestTag.create("fast").hashCode()); assertNotEquals(null, TestTag.create("fast")); assertNotEquals(TestTag.create("fast"), null); } @Test void toStringPrintsName() { assertEquals("fast", TestTag.create("fast").toString()); } private static void yep(String tag) { assertTrue(TestTag.isValid(tag), () -> String.format("'%s' should be a valid tag", tag)); } private static void nope(String tag) { assertFalse(TestTag.isValid(tag), () -> String.format("'%s' should not be a valid tag", tag)); } private void assertSyntaxViolation(String tag) { var exception = assertThrows(PreconditionViolationException.class, () -> TestTag.create(tag)); assertThat(exception).hasMessageStartingWith("Tag name"); assertThat(exception).hasMessageEndingWith("must be syntactically valid"); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdFormatTests.java000066400000000000000000000074531455764576500325060ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.UniqueId.Segment; /** * @since 1.0 */ class UniqueIdFormatTests { @Nested class Formatting { private final UniqueId engineId = UniqueId.root("engine", "junit-jupiter"); private final UniqueIdFormat format = UniqueIdFormat.getDefault(); @Test void engineIdOnly() { assertEquals("[engine:junit-jupiter]", engineId.toString()); assertEquals(format.format(engineId), engineId.toString()); } @Test void withTwoSegments() { var classId = engineId.append("class", "org.junit.MyClass"); assertEquals("[engine:junit-jupiter]/[class:org.junit.MyClass]", classId.toString()); assertEquals(format.format(classId), classId.toString()); } @Test void withManySegments() { var uniqueId = engineId.append("t1", "v1").append("t2", "v2").append("t3", "v3"); assertEquals("[engine:junit-jupiter]/[t1:v1]/[t2:v2]/[t3:v3]", uniqueId.toString()); assertEquals(format.format(uniqueId), uniqueId.toString()); } } @Nested class ParsingWithDefaultFormat implements ParsingTestTrait { private final UniqueIdFormat format = UniqueIdFormat.getDefault(); @Override public UniqueIdFormat getFormat() { return this.format; } @Override public String getEngineUid() { return "[engine:junit-jupiter]"; } @Override public String getMethodUid() { return "[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]"; } } @Nested class ParsingWithCustomFormat implements ParsingTestTrait { private final UniqueIdFormat format = new UniqueIdFormat('{', '=', '}', ','); @Override public UniqueIdFormat getFormat() { return this.format; } @Override public String getEngineUid() { return "{engine=junit-jupiter}"; } @Override public String getMethodUid() { return "{engine=junit-jupiter},{class=MyClass},{method=myMethod}"; } } // ------------------------------------------------------------------------- private static void assertSegment(Segment segment, String expectedType, String expectedValue) { assertEquals(expectedType, segment.getType(), "segment type"); assertEquals(expectedValue, segment.getValue(), "segment value"); } interface ParsingTestTrait { UniqueIdFormat getFormat(); String getEngineUid(); String getMethodUid(); @Test default void parseMalformedUid() { Throwable throwable = assertThrows(JUnitException.class, () -> getFormat().parse("malformed UID")); assertTrue(throwable.getMessage().contains("malformed UID")); } @Test default void parseEngineUid() { var parsedId = getFormat().parse(getEngineUid()); assertSegment(parsedId.getSegments().get(0), "engine", "junit-jupiter"); assertEquals(getEngineUid(), getFormat().format(parsedId)); assertEquals(getEngineUid(), parsedId.toString()); } @Test default void parseMethodUid() { var parsedId = getFormat().parse(getMethodUid()); assertSegment(parsedId.getSegments().get(0), "engine", "junit-jupiter"); assertSegment(parsedId.getSegments().get(1), "class", "MyClass"); assertSegment(parsedId.getSegments().get(2), "method", "myMethod"); assertEquals(getMethodUid(), getFormat().format(parsedId)); assertEquals(getMethodUid(), parsedId.toString()); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdTests.java000066400000000000000000000221751455764576500313330ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.UniqueId.Segment; /** * Unit tests for {@link UniqueId}. * * @since 1.0 * @see org.junit.jupiter.engine.execution.UniqueIdParsingForArrayParameterIntegrationTests */ class UniqueIdTests { private static final String ENGINE_ID = "junit-jupiter"; private static final String SUITE_ENGINE_ID = "junit-platform-suite"; @Nested class Creation { @Test void uniqueIdCanBeCreatedFromEngineId() { var uniqueId = UniqueId.forEngine(ENGINE_ID); assertEquals("[engine:junit-jupiter]", uniqueId.toString()); assertSegment(uniqueId.getSegments().get(0), "engine", "junit-jupiter"); } @Test void engineIdCanBeAppended() { var suiteEngineId = UniqueId.forEngine(SUITE_ENGINE_ID); var uniqueId = suiteEngineId.appendEngine(ENGINE_ID); assertSegment(uniqueId.getSegments().get(1), "engine", "junit-jupiter"); } @Test void retrievingOptionalEngineId() { var uniqueIdWithEngine = UniqueId.forEngine(ENGINE_ID); assertThat(uniqueIdWithEngine.getEngineId()).contains("junit-jupiter"); var uniqueIdWithoutEngine = UniqueId.root("root", "avalue"); assertEquals(Optional.empty(), uniqueIdWithoutEngine.getEngineId()); } @Test void uniqueIdCanBeCreatedFromTypeAndValue() { var uniqueId = UniqueId.root("aType", "aValue"); assertEquals("[aType:aValue]", uniqueId.toString()); assertSegment(uniqueId.getSegments().get(0), "aType", "aValue"); } @Test void rootSegmentCanBeRetrieved() { var uniqueId = UniqueId.root("aType", "aValue"); assertThat(uniqueId.getRoot()).contains(new Segment("aType", "aValue")); } @Test void appendingOneSegment() { var engineId = UniqueId.root("engine", ENGINE_ID); var classId = engineId.append("class", "org.junit.MyClass"); assertThat(classId.getSegments()).hasSize(2); assertSegment(classId.getSegments().get(0), "engine", ENGINE_ID); assertSegment(classId.getSegments().get(1), "class", "org.junit.MyClass"); } @Test void appendingSegmentLeavesOriginalUnchanged() { var uniqueId = UniqueId.root("engine", ENGINE_ID); uniqueId.append("class", "org.junit.MyClass"); assertThat(uniqueId.getSegments()).hasSize(1); assertSegment(uniqueId.getSegments().get(0), "engine", ENGINE_ID); } @Test void appendingSeveralSegments() { var engineId = UniqueId.root("engine", ENGINE_ID); var uniqueId = engineId.append("t1", "v1").append("t2", "v2").append("t3", "v3"); assertThat(uniqueId.getSegments()).hasSize(4); assertSegment(uniqueId.getSegments().get(0), "engine", ENGINE_ID); assertSegment(uniqueId.getSegments().get(1), "t1", "v1"); assertSegment(uniqueId.getSegments().get(2), "t2", "v2"); assertSegment(uniqueId.getSegments().get(3), "t3", "v3"); } @Test void appendingSegmentInstance() { var uniqueId = UniqueId.forEngine(ENGINE_ID).append("t1", "v1"); uniqueId = uniqueId.append(new Segment("t2", "v2")); assertThat(uniqueId.getSegments()).hasSize(3); assertSegment(uniqueId.getSegments().get(0), "engine", ENGINE_ID); assertSegment(uniqueId.getSegments().get(1), "t1", "v1"); assertSegment(uniqueId.getSegments().get(2), "t2", "v2"); } @Test void appendingNullIsNotAllowed() { var uniqueId = UniqueId.forEngine(ENGINE_ID); assertThrows(PreconditionViolationException.class, () -> uniqueId.append(null)); assertThrows(PreconditionViolationException.class, () -> uniqueId.append(null, "foo")); assertThrows(PreconditionViolationException.class, () -> uniqueId.append("foo", null)); } } @Nested class ParsingAndFormatting { @Test void ensureDefaultUniqueIdFormatIsUsedForParsing() { var uniqueIdString = "[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]"; var parsedDirectly = UniqueId.parse(uniqueIdString); var parsedViaFormat = UniqueIdFormat.getDefault().parse(uniqueIdString); assertEquals(parsedViaFormat, parsedDirectly); } @Test void ensureDefaultUniqueIdFormatIsUsedForFormatting() { var parsedDirectly = UniqueId.parse("[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]"); assertEquals("[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]", parsedDirectly.toString()); } @Test void ensureDefaultUniqueIdFormatDecodingEncodesSegmentParts() { var segment = UniqueId.parse("[%5B+%25+%5D):(%3A+%2B+%2F]").getSegments().get(0); assertEquals("[ % ])", segment.getType()); assertEquals("(: + /", segment.getValue()); } @Test void ensureDefaultUniqueIdFormatCanHandleAllCharacters() { for (char c = 0; c < Character.MAX_VALUE; c++) { var value = "foo " + c + " bar"; var uniqueId = UniqueId.parse(UniqueId.root("type", value).toString()); var segment = uniqueId.getSegments().get(0); assertEquals(value, segment.getValue()); } } @ParameterizedTest @ValueSource(strings = { "[a:b]", "[a:b]/[a:b]", "[a$b:b()]", "[a:b(%5BI)]", "[%5B%5D:%3A%2F]" }) void ensureDefaultToStringAndParsingIsIdempotent(String expected) { assertEquals(expected, UniqueId.parse(expected).toString()); } } @Nested class EqualsContract { @Test void sameEnginesAreEqual() { var id1 = UniqueId.root("engine", "junit-jupiter"); var id2 = UniqueId.root("engine", "junit-jupiter"); assertEquals(id2, id1); assertEquals(id1, id2); assertEquals(id1.hashCode(), id2.hashCode()); } @Test void differentEnginesAreNotEqual() { var id1 = UniqueId.root("engine", "junit-vintage"); var id2 = UniqueId.root("engine", "junit-jupiter"); assertNotEquals(id2, id1); assertNotEquals(id1, id2); } @Test void uniqueIdWithSameSegmentsAreEqual() { var id1 = UniqueId.root("engine", "junit-jupiter").append("t1", "v1").append("t2", "v2"); var id2 = UniqueId.root("engine", "junit-jupiter").append("t1", "v1").append("t2", "v2"); assertEquals(id2, id1); assertEquals(id1, id2); assertEquals(id1.hashCode(), id2.hashCode()); } @Test void differentOrderOfSegmentsAreNotEqual() { var id1 = UniqueId.root("engine", "junit-jupiter").append("t2", "v2").append("t1", "v1"); var id2 = UniqueId.root("engine", "junit-jupiter").append("t1", "v1").append("t2", "v2"); assertNotEquals(id2, id1); assertNotEquals(id1, id2); } @Test void additionalSegmentMakesItNotEqual() { var id1 = UniqueId.root("engine", "junit-jupiter").append("t1", "v1"); var id2 = id1.append("t2", "v2"); assertNotEquals(id2, id1); assertNotEquals(id1, id2); } } @Nested class Prefixing { @Test void nullIsNotAPrefix() { var id = UniqueId.forEngine(ENGINE_ID); assertThrows(PreconditionViolationException.class, () -> id.hasPrefix(null)); } @Test void uniqueIdIsPrefixForItself() { var id = UniqueId.forEngine(ENGINE_ID).append("t1", "v1").append("t2", "v2"); assertTrue(id.hasPrefix(id)); } @Test void uniqueIdIsPrefixForUniqueIdWithAdditionalSegments() { var id1 = UniqueId.forEngine(ENGINE_ID); var id2 = id1.append("t1", "v1"); var id3 = id2.append("t2", "v2"); assertFalse(id1.hasPrefix(id2)); assertFalse(id1.hasPrefix(id3)); assertTrue(id2.hasPrefix(id1)); assertFalse(id2.hasPrefix(id3)); assertTrue(id3.hasPrefix(id1)); assertTrue(id3.hasPrefix(id2)); } @Test void completelyUnrelatedUniqueIdsAreNotPrefixesForEachOther() { var id1 = UniqueId.forEngine("foo"); var id2 = UniqueId.forEngine("bar"); assertFalse(id1.hasPrefix(id2)); assertFalse(id2.hasPrefix(id1)); } } @Nested class LastSegment { @Test void returnsLastSegment() { var uniqueId = UniqueId.forEngine("foo"); assertSame(uniqueId.getSegments().get(0), uniqueId.getLastSegment()); uniqueId = UniqueId.forEngine("foo").append("type", "bar"); assertSame(uniqueId.getSegments().get(1), uniqueId.getLastSegment()); } @Test void removesLastSegment() { var uniqueId = UniqueId.forEngine("foo"); assertThrows(PreconditionViolationException.class, uniqueId::removeLastSegment); var newUniqueId = uniqueId.append("type", "bar").removeLastSegment(); assertEquals(uniqueId, newUniqueId); } } private void assertSegment(Segment segment, String expectedType, String expectedValue) { assertEquals(expectedType, segment.getType(), "segment type"); assertEquals(expectedValue, segment.getValue(), "segment value"); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/000077500000000000000000000000001455764576500277225ustar00rootroot00000000000000ClassNameFilterTests.java000066400000000000000000000146301455764576500345510ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * @since 1.0 */ class ClassNameFilterTests { @Test void includeClassNamePatternsChecksPreconditions() { assertThatThrownBy(() -> ClassNameFilter.includeClassNamePatterns((String[]) null)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not be null or empty"); assertThatThrownBy(() -> ClassNameFilter.includeClassNamePatterns(new String[0])) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not be null or empty"); assertThatThrownBy(() -> ClassNameFilter.includeClassNamePatterns(new String[] { null })) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not contain null elements"); } @Test void includeClassNamePatternsWithSinglePattern() { var regex = "^java\\.lang\\..*"; var filter = ClassNameFilter.includeClassNamePatterns(regex); assertThat(filter).hasToString( "IncludeClassNameFilter that includes class names that match one of the following regular expressions: '" + regex + "'"); assertTrue(filter.apply("java.lang.String").included()); assertTrue(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Class name [java.lang.String] matches included pattern: '" + regex + "'"); assertFalse(filter.apply("java.time.Instant").included()); assertFalse(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Class name [java.time.Instant] does not match any included pattern: '" + regex + "'"); } @Test void includeClassNamePatternsWithMultiplePatterns() { var firstRegex = "^java\\.lang\\..*"; var secondRegex = "^java\\.util\\..*"; var filter = ClassNameFilter.includeClassNamePatterns(firstRegex, secondRegex); assertThat(filter).hasToString( "IncludeClassNameFilter that includes class names that match one of the following regular expressions: '" + firstRegex + "' OR '" + secondRegex + "'"); assertTrue(filter.apply("java.lang.String").included()); assertTrue(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Class name [java.lang.String] matches included pattern: '" + firstRegex + "'"); assertTrue(filter.apply("java.util.Collection").included()); assertTrue(filter.toPredicate().test("java.util.Collection")); assertThat(filter.apply("java.util.Collection").getReason()).contains( "Class name [java.util.Collection] matches included pattern: '" + secondRegex + "'"); assertFalse(filter.apply("java.time.Instant").included()); assertFalse(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Class name [java.time.Instant] does not match any included pattern: '" + firstRegex + "' OR '" + secondRegex + "'"); } @Test void excludeClassNamePatternsChecksPreconditions() { assertThatThrownBy(() -> ClassNameFilter.excludeClassNamePatterns((String[]) null)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not be null or empty"); assertThatThrownBy(() -> ClassNameFilter.excludeClassNamePatterns(new String[0])) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not be null or empty"); assertThatThrownBy(() -> ClassNameFilter.excludeClassNamePatterns(new String[] { null })) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("patterns array must not contain null elements"); } @Test void excludeClassNamePatternsWithSinglePattern() { var regex = "^java\\.lang\\..*"; var filter = ClassNameFilter.excludeClassNamePatterns(regex); assertThat(filter).hasToString( "ExcludeClassNameFilter that excludes class names that match one of the following regular expressions: '" + regex + "'"); assertTrue(filter.apply("java.lang.String").excluded()); assertFalse(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Class name [java.lang.String] matches excluded pattern: '" + regex + "'"); assertTrue(filter.apply("java.time.Instant").included()); assertTrue(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Class name [java.time.Instant] does not match any excluded pattern: '" + regex + "'"); } @Test void excludeClassNamePatternsWithMultiplePatterns() { var firstRegex = "^java\\.lang\\..*"; var secondRegex = "^java\\.util\\..*"; var filter = ClassNameFilter.excludeClassNamePatterns(firstRegex, secondRegex); assertThat(filter).hasToString( "ExcludeClassNameFilter that excludes class names that match one of the following regular expressions: '" + firstRegex + "' OR '" + secondRegex + "'"); assertTrue(filter.apply("java.lang.String").excluded()); assertFalse(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Class name [java.lang.String] matches excluded pattern: '" + firstRegex + "'"); assertTrue(filter.apply("java.util.Collection").excluded()); assertFalse(filter.toPredicate().test("java.util.Collection")); assertThat(filter.apply("java.util.Collection").getReason()).contains( "Class name [java.util.Collection] matches excluded pattern: '" + secondRegex + "'"); assertFalse(filter.apply("java.time.Instant").excluded()); assertTrue(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Class name [java.time.Instant] does not match any excluded pattern: '" + firstRegex + "' OR '" + secondRegex + "'"); } } ClassSelectorTests.java000066400000000000000000000031601455764576500342770ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link ClassSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class ClassSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new ClassSelector(null, "org.example.TestClass"); var selector2 = new ClassSelector(null, "org.example.TestClass"); var selector3 = new ClassSelector(null, "org.example.X"); assertEqualsAndHashCode(selector1, selector2, selector3); } @Test void preservesOriginalExceptionWhenTryingToLoadClass() { var selector = new ClassSelector(null, "org.example.TestClass"); var e = assertThrows(PreconditionViolationException.class, selector::getJavaClass); assertThat(e).hasMessage("Could not load class with name: org.example.TestClass").hasCauseInstanceOf( ClassNotFoundException.class); } @Test void usesClassClassLoader() { var selector = new ClassSelector(getClass()); assertThat(selector.getClassLoader()).isNotNull().isSameAs(getClass().getClassLoader()); } } ClasspathResourceSelectorTests.java000066400000000000000000000024661455764576500366740ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link ClasspathResourceSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class ClasspathResourceSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new ClasspathResourceSelector("/foo/bar.txt", null); var selector2 = new ClasspathResourceSelector("/foo/bar.txt", null); var selector3 = new ClasspathResourceSelector("/foo/X.txt", null); assertEqualsAndHashCode(selector1, selector2, selector3); } @Test void equalsAndHashCodeWithFilePosition() { var selector1 = new ClasspathResourceSelector("/foo/bar.txt", FilePosition.from(1)); var selector2 = new ClasspathResourceSelector("/foo/bar.txt", FilePosition.from(1)); var selector3 = new ClasspathResourceSelector("/foo/bar.txt", FilePosition.from(2)); assertEqualsAndHashCode(selector1, selector2, selector3); } } ClasspathRootSelectorTests.java000066400000000000000000000017571455764576500360320ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import java.net.URI; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link ClasspathRootSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class ClasspathRootSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() throws Exception { var selector1 = new ClasspathRootSelector(new URI("file://example/path")); var selector2 = new ClasspathRootSelector(new URI("file://example/path")); var selector3 = new ClasspathRootSelector(new URI("file://example/foo")); assertEqualsAndHashCode(selector1, selector2, selector3); } } DirectorySelectorTests.java000066400000000000000000000016051455764576500352000ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link DirectorySelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class DirectorySelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new DirectorySelector("/example/foo"); var selector2 = new DirectorySelector("/example/foo"); var selector3 = new DirectorySelector("/example/bar"); assertEqualsAndHashCode(selector1, selector2, selector3); } } DiscoverySelectorsTests.java000066400000000000000000001351531455764576500353740ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static java.lang.String.join; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathResource; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectFile; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModule; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModules; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectNestedClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectNestedMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; import java.io.File; import java.lang.reflect.Method; import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.test.TestClassLoader; import org.junit.platform.commons.util.ReflectionUtils; /** * Unit tests for {@link DiscoverySelectors}. * * @since 1.0 */ class DiscoverySelectorsTests { @Nested class SelectUriTests { @Test void selectUriByName() { assertViolatesPrecondition(() -> selectUri((String) null)); assertViolatesPrecondition(() -> selectUri(" ")); assertViolatesPrecondition(() -> selectUri("foo:")); var uri = "https://junit.org"; var selector = selectUri(uri); assertEquals(uri, selector.getUri().toString()); } @Test void selectUriByURI() throws Exception { assertViolatesPrecondition(() -> selectUri((URI) null)); assertViolatesPrecondition(() -> selectUri(" ")); var uri = new URI("https://junit.org"); var selector = selectUri(uri); assertEquals(uri, selector.getUri()); } } @Nested class SelectFileTests { @Test void selectFileByName() { assertViolatesPrecondition(() -> selectFile((String) null)); assertViolatesPrecondition(() -> selectFile(" ")); var path = "src/test/resources/do_not_delete_me.txt"; var selector = selectFile(path); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getFile()); assertEquals(Paths.get(path), selector.getPath()); } @Test void selectFileByNameAndPosition() { var filePosition = FilePosition.from(12, 34); assertViolatesPrecondition(() -> selectFile((String) null, filePosition)); assertViolatesPrecondition(() -> selectFile(" ", filePosition)); var path = "src/test/resources/do_not_delete_me.txt"; var selector = selectFile(path, filePosition); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getFile()); assertEquals(Paths.get(path), selector.getPath()); assertEquals(filePosition, selector.getPosition().get()); } @Test void selectFileByFileReference() throws Exception { assertViolatesPrecondition(() -> selectFile((File) null)); assertViolatesPrecondition(() -> selectFile(new File("bogus/nonexistent.txt"))); var currentDir = new File(".").getCanonicalFile(); var relativeDir = new File("..", currentDir.getName()); var file = new File(relativeDir, "src/test/resources/do_not_delete_me.txt"); var path = file.getCanonicalFile().getPath(); var selector = selectFile(file); assertEquals(path, selector.getRawPath()); assertEquals(file.getCanonicalFile(), selector.getFile()); assertEquals(Paths.get(path), selector.getPath()); } @Test void selectFileByFileReferenceAndPosition() throws Exception { var filePosition = FilePosition.from(12, 34); assertViolatesPrecondition(() -> selectFile((File) null, filePosition)); assertViolatesPrecondition(() -> selectFile(new File("bogus/nonexistent.txt"), filePosition)); var currentDir = new File(".").getCanonicalFile(); var relativeDir = new File("..", currentDir.getName()); var file = new File(relativeDir, "src/test/resources/do_not_delete_me.txt"); var path = file.getCanonicalFile().getPath(); var selector = selectFile(file, filePosition); assertEquals(path, selector.getRawPath()); assertEquals(file.getCanonicalFile(), selector.getFile()); assertEquals(Paths.get(path), selector.getPath()); assertEquals(FilePosition.from(12, 34), selector.getPosition().get()); } } @Nested class SelectDirectoryTests { @Test void selectDirectoryByName() { assertViolatesPrecondition(() -> selectDirectory((String) null)); assertViolatesPrecondition(() -> selectDirectory(" ")); var path = "src/test/resources"; var selector = selectDirectory(path); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getDirectory()); assertEquals(Paths.get(path), selector.getPath()); } @Test void selectDirectoryByFileReference() throws Exception { assertViolatesPrecondition(() -> selectDirectory((File) null)); assertViolatesPrecondition(() -> selectDirectory(new File("bogus/nonexistent"))); var currentDir = new File(".").getCanonicalFile(); var relativeDir = new File("..", currentDir.getName()); var directory = new File(relativeDir, "src/test/resources"); var path = directory.getCanonicalFile().getPath(); var selector = selectDirectory(directory); assertEquals(path, selector.getRawPath()); assertEquals(directory.getCanonicalFile(), selector.getDirectory()); assertEquals(Paths.get(path), selector.getPath()); } } @Nested class SelectClasspathResourceTests { @Test void selectClasspathResources() { assertViolatesPrecondition(() -> selectClasspathResource(null)); assertViolatesPrecondition(() -> selectClasspathResource("")); assertViolatesPrecondition(() -> selectClasspathResource(" ")); assertViolatesPrecondition(() -> selectClasspathResource("\t")); // with unnecessary "/" prefix var selector = selectClasspathResource("/foo/bar/spec.xml"); assertEquals("foo/bar/spec.xml", selector.getClasspathResourceName()); // standard use case selector = selectClasspathResource("A/B/C/spec.json"); assertEquals("A/B/C/spec.json", selector.getClasspathResourceName()); } @Test void selectClasspathResourcesWithFilePosition() { var filePosition = FilePosition.from(12, 34); assertViolatesPrecondition(() -> selectClasspathResource(null, filePosition)); assertViolatesPrecondition(() -> selectClasspathResource("", filePosition)); assertViolatesPrecondition(() -> selectClasspathResource(" ", filePosition)); assertViolatesPrecondition(() -> selectClasspathResource("\t", filePosition)); // with unnecessary "/" prefix var selector = selectClasspathResource("/foo/bar/spec.xml", filePosition); assertEquals("foo/bar/spec.xml", selector.getClasspathResourceName()); assertEquals(FilePosition.from(12, 34), selector.getPosition().get()); // standard use case selector = selectClasspathResource("A/B/C/spec.json", filePosition); assertEquals("A/B/C/spec.json", selector.getClasspathResourceName()); assertEquals(filePosition, selector.getPosition().get()); } } @Nested class SelectModuleTests { @Test void selectModuleByName() { var selector = selectModule("java.base"); assertEquals("java.base", selector.getModuleName()); } @Test void selectModuleByNamePreconditions() { assertViolatesPrecondition(() -> selectModule(null)); assertViolatesPrecondition(() -> selectModule("")); assertViolatesPrecondition(() -> selectModule(" ")); } @Test void selectModulesByNames() { var selectors = selectModules(Set.of("a", "b")); var names = selectors.stream().map(ModuleSelector::getModuleName).collect(Collectors.toList()); assertThat(names).containsExactlyInAnyOrder("b", "a"); } @Test void selectModulesByNamesPreconditions() { assertViolatesPrecondition(() -> selectModules(null)); assertViolatesPrecondition(() -> selectModules(Set.of("a", " "))); } } @Nested class SelectPackageTests { @Test void selectPackageByName() { var selector = selectPackage(getClass().getPackage().getName()); assertEquals(getClass().getPackage().getName(), selector.getPackageName()); } } @Nested class SelectClasspathRootsTests { @Test void selectClasspathRootsWithNonExistingDirectory() { var selectors = selectClasspathRoots(Set.of(Paths.get("some", "local", "path"))); assertThat(selectors).isEmpty(); } @Test void selectClasspathRootsWithNonExistingJarFile() { var selectors = selectClasspathRoots(Set.of(Paths.get("some.jar"))); assertThat(selectors).isEmpty(); } @Test void selectClasspathRootsWithExistingDirectory(@TempDir Path tempDir) { var selectors = selectClasspathRoots(Set.of(tempDir)); assertThat(selectors).extracting(ClasspathRootSelector::getClasspathRoot).containsExactly(tempDir.toUri()); } @Test void selectClasspathRootsWithExistingJarFile() throws Exception { var jarUri = getClass().getResource("/jartest.jar").toURI(); var jarFile = Paths.get(jarUri); var selectors = selectClasspathRoots(Set.of(jarFile)); assertThat(selectors).extracting(ClasspathRootSelector::getClasspathRoot).containsExactly(jarUri); } } @Nested class SelectClassTests { @Test void selectClassByName() { var selector = selectClass(getClass().getName()); assertEquals(getClass(), selector.getJavaClass()); } @Test void selectClassByNameWithExplicitClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(getClass())) { var selector = selectClass(testClassLoader, getClass().getName()); assertThat(selector.getJavaClass().getName()).isEqualTo(getClass().getName()); assertThat(selector.getJavaClass()).isNotEqualTo(getClass()); assertThat(selector.getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getJavaClass().getClassLoader()).isSameAs(testClassLoader); } } } @Nested class SelectMethodTests { @Test @DisplayName("Preconditions: selectMethod(className, methodName)") void selectMethodByClassNameAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectMethod("TestClass", (String) null)); assertViolatesPrecondition(() -> selectMethod("TestClass", "")); assertViolatesPrecondition(() -> selectMethod("TestClass", " ")); assertViolatesPrecondition(() -> selectMethod((String) null, "method")); assertViolatesPrecondition(() -> selectMethod("", "method")); assertViolatesPrecondition(() -> selectMethod(" ", "method")); } @Test @DisplayName("Preconditions: selectMethod(className, methodName, parameterTypeNames)") void selectMethodByClassNameMethodNameAndParameterTypeNamesPreconditions() { assertViolatesPrecondition(() -> selectMethod("TestClass", null, "int")); assertViolatesPrecondition(() -> selectMethod("TestClass", "", "int")); assertViolatesPrecondition(() -> selectMethod("TestClass", " ", "int")); assertViolatesPrecondition(() -> selectMethod((String) null, "method", "int")); assertViolatesPrecondition(() -> selectMethod("", "method", "int")); assertViolatesPrecondition(() -> selectMethod(" ", "method", "int")); assertViolatesPrecondition(() -> selectMethod("TestClass", "method", (String) null)); } @Test @DisplayName("Preconditions: selectMethod(className, methodName, parameterTypes)") void selectMethodByClassNameMethodNameAndParameterTypesPreconditions() { assertViolatesPrecondition(() -> selectMethod("TestClass", null, int.class)); assertViolatesPrecondition(() -> selectMethod("TestClass", "", int.class)); assertViolatesPrecondition(() -> selectMethod("TestClass", " ", int.class)); assertViolatesPrecondition(() -> selectMethod((String) null, "method", int.class)); assertViolatesPrecondition(() -> selectMethod("", "method", int.class)); assertViolatesPrecondition(() -> selectMethod(" ", "method", int.class)); assertViolatesPrecondition(() -> selectMethod("TestClass", "method", (Class) null)); assertViolatesPrecondition(() -> selectMethod("TestClass", "method", new Class[] { int.class, null })); } @Test @DisplayName("Preconditions: selectMethod(class, methodName)") void selectMethodByClassAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectMethod(testClass(), (String) null)); assertViolatesPrecondition(() -> selectMethod(testClass(), "")); assertViolatesPrecondition(() -> selectMethod(testClass(), " ")); assertViolatesPrecondition(() -> selectMethod((Class) null, "method")); } @Test @DisplayName("Preconditions: selectMethod(class, methodName, parameterTypeNames)") void selectMethodByClassMethodNameAndParameterTypeNamesPreconditions() { assertViolatesPrecondition(() -> selectMethod((Class) null, "method", "int")); assertViolatesPrecondition(() -> selectMethod(testClass(), null, "int")); assertViolatesPrecondition(() -> selectMethod(testClass(), "", "int")); assertViolatesPrecondition(() -> selectMethod(testClass(), " ", "int")); assertViolatesPrecondition(() -> selectMethod(testClass(), "method", (String) null)); } @Test @DisplayName("Preconditions: selectMethod(class, method)") void selectMethodByClassAndMethodPreconditions() { var method = getClass().getDeclaredMethods()[0]; assertViolatesPrecondition(() -> selectMethod(null, method)); assertViolatesPrecondition(() -> selectMethod(testClass(), (Method) null)); } @ParameterizedTest(name = "FQMN: ''{0}''") @MethodSource("invalidFullyQualifiedMethodNames") @DisplayName("Preconditions: selectMethod(FQMN)") void selectMethodByFullyQualifiedNamePreconditions(String fqmn, String message) { Exception exception = assertThrows(PreconditionViolationException.class, () -> selectMethod(fqmn)); assertThat(exception).hasMessageContaining(message); } static Stream invalidFullyQualifiedMethodNames() { // @formatter:off return Stream.of( arguments(null, "must not be null or blank"), arguments("", "must not be null or blank"), arguments(" ", "must not be null or blank"), arguments("com.example", "not a valid fully qualified method name"), arguments("com.example.Foo", "not a valid fully qualified method name"), arguments("method", "not a valid fully qualified method name"), arguments("#method", "not a valid fully qualified method name"), arguments("#method()", "not a valid fully qualified method name"), arguments("#method(int)", "not a valid fully qualified method name"), arguments("java.lang.String#", "not a valid fully qualified method name") ); // @formatter:on } @Test void selectMethodByFullyQualifiedName() throws Exception { Class clazz = testClass(); var method = clazz.getDeclaredMethod("myTest"); assertSelectMethodByFullyQualifiedName(clazz, method); } @Test void selectMethodByFullyQualifiedNameWithExplicitClassLoader() throws Exception { try (var testClassLoader = TestClassLoader.forClasses(testClass())) { var clazz = testClassLoader.loadClass(testClass().getName()); assertThat(clazz).isNotEqualTo(testClass()); var method = clazz.getDeclaredMethod("myTest"); var selector = selectMethod(testClassLoader, testClass().getName(), "myTest"); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getJavaClass()).isEqualTo(clazz); assertThat(selector.getClassName()).isEqualTo(clazz.getName()); assertThat(selector.getMethodName()).isEqualTo(method.getName()); assertThat(selector.getParameterTypeNames()).isEmpty(); } } @Test void selectMethodByFullyQualifiedNameForDefaultMethodInInterface() throws Exception { Class clazz = TestCaseWithDefaultMethod.class; var method = clazz.getMethod("myTest"); assertSelectMethodByFullyQualifiedName(clazz, method); } @Test void selectMethodByFullyQualifiedNameWithPrimitiveParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", int.class); assertSelectMethodByFullyQualifiedName(testClass(), method, int.class, "int"); } @Test void selectMethodByFullyQualifiedNameWithPrimitiveParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", int.class); assertSelectMethodByFullyQualifiedName(testClass(), method, "int", "int"); } @Test void selectMethodByFullyQualifiedNameWithObjectParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", String.class); assertSelectMethodByFullyQualifiedName(testClass(), method, String.class, String.class.getName()); } @Test void selectMethodByFullyQualifiedNameWithObjectParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", String.class); assertSelectMethodByFullyQualifiedName(testClass(), method, "java.lang.String", String.class.getName()); } @Test void selectMethodByFullyQualifiedNameWithPrimitiveArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[].class); assertSelectMethodByFullyQualifiedName(testClass(), method, int[].class, int[].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithPrimitiveArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "int[]", "int[]"); } @Test void selectMethodByFullyQualifiedNameWithObjectArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", String[].class); assertSelectMethodByFullyQualifiedName(testClass(), method, String[].class, String[].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithObjectArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", String[].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "java.lang.String[]", "java.lang.String[]"); } @Test void selectMethodByFullyQualifiedNameWithTwoDimensionalPrimitiveArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, int[][].class, int[][].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithTwoDimensionalPrimitiveArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "int[][]", "int[][]"); } @Test void selectMethodByFullyQualifiedNameWithTwoDimensionalObjectArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", String[][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, String[][].class, String[][].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithTwoDimensionalObjectArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", String[][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "java.lang.String[][]", "java.lang.String[][]"); } @Test void selectMethodByFullyQualifiedNameWithMultidimensionalPrimitiveArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[][][][][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, int[][][][][].class, int[][][][][].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithMultidimensionalPrimitiveArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", int[][][][][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "int[][][][][]", "int[][][][][]"); } @Test void selectMethodByFullyQualifiedNameWithMultidimensionalObjectArrayParameter() throws Exception { var method = testClass().getDeclaredMethod("myTest", Double[][][][][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, Double[][][][][].class, Double[][][][][].class.getName()); } @Test void selectMethodByFullyQualifiedNameWithMultidimensionalObjectArrayParameterUsingSourceCodeSyntax() throws Exception { var method = testClass().getDeclaredMethod("myTest", Double[][][][][].class); assertSelectMethodByFullyQualifiedName(testClass(), method, "java.lang.Double[][][][][]", "java.lang.Double[][][][][]"); } @Test void selectMethodByFullyQualifiedNameEndingInOpeningParenthesis() { var className = "org.example.MyClass"; // The following bizarre method name is not permissible in Java source // code; however, it's permitted by the JVM -- for example, in Groovy // or Kotlin source code using back ticks. var methodName = ")--("; var fqmn = className + "#" + methodName; var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } /** * Inspired by Spock specifications. */ @Test void selectMethodByFullyQualifiedNameContainingHashtags() { var className = "org.example.CalculatorSpec"; var methodName = "#a plus #b equals #c"; var fqmn = className + "#" + methodName; var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } /** * Inspired by Spock specifications. */ @Test void selectMethodByFullyQualifiedNameContainingHashtagsAndWithParameterList() { var className = "org.example.CalculatorSpec"; var methodName = "#a plus #b equals #c"; var methodParameters = "int, int, int"; var fqmn = String.format("%s#%s(%s)", className, methodName, methodParameters); var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals(methodParameters, selector.getParameterTypeNames()); } /** * Inspired by Kotlin tests. */ @Test void selectMethodByFullyQualifiedNameContainingParentheses() { var className = "org.example.KotlinTestCase"; var methodName = "🦆 ~|~test with a really, (really) terrible name & that needs to be changed!~|~"; var fqmn = className + "#" + methodName; var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } /** * Inspired by Kotlin tests. */ @Test void selectMethodByFullyQualifiedNameEndingWithParentheses() { var className = "org.example.KotlinTestCase"; var methodName = "test name ends with parentheses()"; var fqmn = className + "#" + methodName + "()"; var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } /** * Inspired by Kotlin tests. */ @Test void selectMethodByFullyQualifiedNameEndingWithParenthesesAndWithParameterList() { var className = "org.example.KotlinTestCase"; var methodName = "test name ends with parentheses()"; var methodParameters = "int, int, int"; var fqmn = String.format("%s#%s(%s)", className, methodName, methodParameters); var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals(methodParameters, selector.getParameterTypeNames()); } private void assertSelectMethodByFullyQualifiedName(Class clazz, Method method) { var selector = selectMethod(fqmn(clazz, method.getName())); assertEquals(method, selector.getJavaMethod()); assertEquals(clazz, selector.getJavaClass()); assertEquals(clazz.getName(), selector.getClassName()); assertEquals(method.getName(), selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } private void assertSelectMethodByFullyQualifiedName(Class clazz, Method method, Class parameterType, String expectedParameterTypes) { var selector = selectMethod(fqmn(parameterType)); assertEquals(method, selector.getJavaMethod()); assertEquals(clazz, selector.getJavaClass()); assertEquals(clazz.getName(), selector.getClassName()); assertEquals(method.getName(), selector.getMethodName()); assertEquals(expectedParameterTypes, selector.getParameterTypeNames()); } private void assertSelectMethodByFullyQualifiedName(Class clazz, Method method, String parameterName, String expectedParameterTypes) { var selector = selectMethod(fqmnWithParamNames(parameterName)); assertEquals(method, selector.getJavaMethod()); assertEquals(clazz, selector.getJavaClass()); assertEquals(clazz.getName(), selector.getClassName()); assertEquals(method.getName(), selector.getMethodName()); assertEquals(expectedParameterTypes, selector.getParameterTypeNames()); } @Test void selectMethodByClassAndMethodName() throws Exception { var method = testClass().getDeclaredMethod("myTest"); var selector = selectMethod(testClass(), "myTest"); assertEquals(testClass(), selector.getJavaClass()); assertEquals(testClass().getName(), selector.getClassName()); assertEquals(method, selector.getJavaMethod()); assertEquals("myTest", selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } @Test void selectMethodByClassMethodNameAndParameterTypeNames() throws Exception { var testClass = testClass(); var method = testClass.getDeclaredMethod("myTest", String.class, boolean[].class); var selector = selectMethod(testClass, "myTest", "java.lang.String, boolean[]"); assertThat(selector.getClassName()).isEqualTo(testClass.getName()); assertThat(selector.getJavaClass()).isEqualTo(testClass); assertThat(selector.getMethodName()).isEqualTo("myTest"); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String, boolean[]"); assertThat(selector.getParameterTypes()).containsExactly(String.class, boolean[].class); } @Test void selectMethodByClassNameMethodNameAndParameterTypes() throws Exception { var testClass = testClass(); var method = testClass.getDeclaredMethod("myTest", String.class, boolean[].class); var selector = selectMethod(testClass.getName(), "myTest", String.class, boolean[].class); assertThat(selector.getClassName()).isEqualTo(testClass.getName()); assertThat(selector.getJavaClass()).isEqualTo(testClass); assertThat(selector.getMethodName()).isEqualTo("myTest"); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String, boolean[]"); assertThat(selector.getParameterTypes()).containsExactly(String.class, boolean[].class); } @Test void selectMethodByClassNameMethodNameAndParameterTypeNamesWithExplicitClassLoader() throws Exception { var testClass = testClass(); try (var testClassLoader = TestClassLoader.forClasses(testClass)) { var clazz = testClassLoader.loadClass(testClass.getName()); assertThat(clazz).isNotEqualTo(testClass); var method = clazz.getDeclaredMethod("myTest", String.class, boolean[].class); var selector = selectMethod(testClassLoader, testClass.getName(), "myTest", "java.lang.String, boolean[]"); assertThat(selector.getClassName()).isEqualTo(clazz.getName()); assertThat(selector.getJavaClass()).isEqualTo(clazz); assertThat(selector.getMethodName()).isEqualTo(method.getName()); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String, boolean[]"); assertThat(selector.getParameterTypes()).containsExactly(String.class, boolean[].class); } } @Test void selectMethodByClassMethodNameAndParameterTypes() throws Exception { var testClass = testClass(); var method = testClass.getDeclaredMethod("myTest", String.class, boolean[].class); var selector = selectMethod(testClass, "myTest", String.class, boolean[].class); assertThat(selector.getClassName()).isEqualTo(testClass.getName()); assertThat(selector.getJavaClass()).isEqualTo(testClass); assertThat(selector.getMethodName()).isEqualTo("myTest"); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String, boolean[]"); assertThat(selector.getParameterTypes()).containsExactly(String.class, boolean[].class); } @Test void selectMethodWithParametersByMethodReference() throws Exception { var testClass = testClass(); var method = testClass.getDeclaredMethod("myTest", String.class, boolean[].class); var selector = selectMethod(testClass, method); assertThat(selector.getClassName()).isEqualTo(testClass.getName()); assertThat(selector.getJavaClass()).isEqualTo(testClass); assertThat(selector.getMethodName()).isEqualTo("myTest"); assertThat(selector.getJavaMethod()).isEqualTo(method); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String, boolean[]"); assertThat(selector.getParameterTypes()).containsExactly(String.class, boolean[].class); } @Test void selectClassByNameForSpockSpec() { var className = "org.example.CalculatorSpec"; var selector = selectClass(className); assertEquals(className, selector.getClassName()); } @Test void selectMethodByClassAndNameForSpockSpec() { var className = "org.example.CalculatorSpec"; var methodName = "#a plus #b equals #c"; var selector = selectMethod(className, methodName); assertEquals(className, selector.getClassName()); assertEquals(methodName, selector.getMethodName()); assertEquals("", selector.getParameterTypeNames()); } private static Class testClass() { return DiscoverySelectorsTests.class; } } @Nested class SelectNestedClassAndSelectNestedMethodTests { private final String enclosingClassName = getClass().getName() + "$ClassWithNestedInnerClass"; private final String nestedClassName = getClass().getName() + "$ClassWithNestedInnerClass$NestedClass"; private final String doubleNestedClassName = nestedClassName + "$DoubleNestedClass"; private final String methodName = "nestedTest"; @Test void selectNestedClassByClassNames() { var selector = selectNestedClass(List.of(enclosingClassName), nestedClassName); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); } @Test void selectNestedClassByClassNamesWithExplicitClassLoader() throws Exception { var testClasses = List.of(ClassWithNestedInnerClass.class, ClassWithNestedInnerClass.NestedClass.class); try (var testClassLoader = TestClassLoader.forClasses(testClasses)) { var selector = selectNestedClass(testClassLoader, List.of(enclosingClassName), nestedClassName); assertThat(selector.getEnclosingClasses()).doesNotContain(ClassWithNestedInnerClass.class); assertThat(selector.getEnclosingClasses()).extracting(Class::getName).containsOnly(enclosingClassName); assertThat(selector.getNestedClass()).isNotEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getNestedClass().getName()).isEqualTo(nestedClassName); assertThat(selector.getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getEnclosingClasses()).extracting(Class::getClassLoader).containsOnly( testClassLoader); assertThat(selector.getNestedClass().getClassLoader()).isSameAs(testClassLoader); } } @Test void selectDoubleNestedClassByClassNames() { var selector = selectNestedClass(List.of(enclosingClassName, nestedClassName), doubleNestedClassName); assertThat(selector.getEnclosingClasses()).containsExactly(ClassWithNestedInnerClass.class, ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getNestedClass()).isEqualTo( ClassWithNestedInnerClass.NestedClass.DoubleNestedClass.class); assertThat(selector.getEnclosingClassNames()).containsExactly(enclosingClassName, nestedClassName); assertThat(selector.getNestedClassName()).isEqualTo(doubleNestedClassName); } @Test void selectNestedClassPreconditions() { assertViolatesPrecondition(() -> selectNestedClass(null, "ClassName")); assertViolatesPrecondition(() -> selectNestedClass(List.of(), "ClassName")); assertViolatesPrecondition(() -> selectNestedClass(List.of("ClassName"), null)); assertViolatesPrecondition(() -> selectNestedClass(List.of("ClassName"), "")); assertViolatesPrecondition(() -> selectNestedClass(List.of("ClassName"), " ")); } @Test void selectNestedMethodByEnclosingClassNamesAndMethodName() throws Exception { var selector = selectNestedMethod(List.of(enclosingClassName), nestedClassName, methodName); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getMethod()).isEqualTo(selector.getNestedClass().getDeclaredMethod(methodName)); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); assertThat(selector.getMethodName()).isEqualTo(methodName); } @Test void selectNestedMethodByEnclosingClassNamesAndMethodNameWithExplicitClassLoader() throws Exception { var testClasses = List.of(ClassWithNestedInnerClass.class, ClassWithNestedInnerClass.NestedClass.class); try (var testClassLoader = TestClassLoader.forClasses(testClasses)) { var selector = selectNestedMethod(testClassLoader, List.of(enclosingClassName), nestedClassName, methodName); assertThat(selector.getEnclosingClasses()).doesNotContain(ClassWithNestedInnerClass.class); assertThat(selector.getEnclosingClasses()).extracting(Class::getName).containsOnly(enclosingClassName); assertThat(selector.getNestedClass()).isNotEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getNestedClass().getName()).isEqualTo(nestedClassName); assertThat(selector.getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getEnclosingClasses()).extracting(Class::getClassLoader).containsOnly( testClassLoader); assertThat(selector.getNestedClass().getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getMethodName()).isEqualTo(methodName); } } @Test void selectNestedMethodByEnclosingClassesAndMethodName() throws Exception { var selector = selectNestedMethod(List.of(ClassWithNestedInnerClass.class), ClassWithNestedInnerClass.NestedClass.class, methodName); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getMethod()).isEqualTo(selector.getNestedClass().getDeclaredMethod(methodName)); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); assertThat(selector.getMethodName()).isEqualTo(methodName); } @Test void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypeNames() throws Exception { var selector = selectNestedMethod(List.of(enclosingClassName), nestedClassName, methodName, String.class.getName()); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getMethod()).isEqualTo( selector.getNestedClass().getDeclaredMethod(methodName, String.class)); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); assertThat(selector.getMethodName()).isEqualTo(methodName); } /** * @since 1.0 */ @Test void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypes() throws Exception { var selector = selectNestedMethod(List.of(enclosingClassName), nestedClassName, methodName, String.class); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getMethod()).isEqualTo( selector.getNestedClass().getDeclaredMethod(methodName, String.class)); assertThat(selector.getParameterTypes()).containsExactly(String.class); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); assertThat(selector.getMethodName()).isEqualTo(methodName); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String"); } /** * @since 1.10 */ @Test void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypeNamesWithExplicitClassLoader() throws Exception { var enclosingClass = ClassWithNestedInnerClass.class; var nestedClass = ClassWithNestedInnerClass.NestedClass.class; try (var testClassLoader = TestClassLoader.forClasses(enclosingClass, nestedClass)) { var selector = selectNestedMethod(testClassLoader, List.of(enclosingClassName), nestedClassName, methodName, String.class.getName()); assertThat(selector.getEnclosingClasses()).doesNotContain(enclosingClass); assertThat(selector.getEnclosingClasses()).extracting(Class::getName).containsOnly(enclosingClassName); assertThat(selector.getNestedClass()).isNotEqualTo(nestedClass); assertThat(selector.getNestedClass().getName()).isEqualTo(nestedClassName); assertThat(selector.getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getEnclosingClasses()).extracting(Class::getClassLoader).containsOnly( testClassLoader); assertThat(selector.getNestedClass().getClassLoader()).isSameAs(testClassLoader); assertThat(selector.getMethodName()).isEqualTo(methodName); assertThat(selector.getParameterTypeNames()).isEqualTo(String.class.getName()); } } /** * @since 1.10 */ @Test void selectNestedMethodByEnclosingClassesMethodNameAndParameterTypes() throws Exception { var selector = selectNestedMethod(List.of(ClassWithNestedInnerClass.class), ClassWithNestedInnerClass.NestedClass.class, methodName, String.class); assertThat(selector.getEnclosingClasses()).containsOnly(ClassWithNestedInnerClass.class); assertThat(selector.getNestedClass()).isEqualTo(ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getMethod()).isEqualTo( selector.getNestedClass().getDeclaredMethod(methodName, String.class)); assertThat(selector.getParameterTypes()).containsExactly(String.class); assertThat(selector.getEnclosingClassNames()).containsOnly(enclosingClassName); assertThat(selector.getNestedClassName()).isEqualTo(nestedClassName); assertThat(selector.getMethodName()).isEqualTo(methodName); assertThat(selector.getParameterTypeNames()).isEqualTo("java.lang.String"); } @Test void selectDoubleNestedMethodByEnclosingClassNamesAndMethodName() throws Exception { var doubleNestedMethodName = "doubleNestedTest"; var selector = selectNestedMethod(List.of(enclosingClassName, nestedClassName), doubleNestedClassName, doubleNestedMethodName); assertThat(selector.getEnclosingClasses()).containsExactly(ClassWithNestedInnerClass.class, ClassWithNestedInnerClass.NestedClass.class); assertThat(selector.getNestedClass()).isEqualTo( ClassWithNestedInnerClass.NestedClass.DoubleNestedClass.class); assertThat(selector.getMethod()).isEqualTo( selector.getNestedClass().getDeclaredMethod(doubleNestedMethodName)); assertThat(selector.getEnclosingClassNames()).containsExactly(enclosingClassName, nestedClassName); assertThat(selector.getNestedClassName()).isEqualTo(doubleNestedClassName); assertThat(selector.getMethodName()).isEqualTo(doubleNestedMethodName); } @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName)") void selectNestedMethodByEnclosingClassNamesAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectNestedMethod(null, "ClassName", "methodName")); assertViolatesPrecondition(() -> selectNestedMethod(List.of(), "ClassName", "methodName")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), null, "methodName")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), " ", "methodName")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", null)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", " ")); } @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName, parameterTypeNames)") void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypeNamesPreconditions() { assertViolatesPrecondition(() -> selectNestedMethod(null, "ClassName", "methodName", "int")); assertViolatesPrecondition(() -> selectNestedMethod(List.of(), "ClassName", "methodName", "int")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), null, "methodName", "int")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), " ", "methodName", "int")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", null, "int")); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", " ", "int")); assertViolatesPrecondition( () -> selectNestedMethod(List.of("ClassName"), "ClassName", "methodName", (String) null)); } /** * @since 1.10 */ @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName, parameterTypes)") void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypesPreconditions() { assertViolatesPrecondition(() -> selectNestedMethod(null, "ClassName", "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of(), "ClassName", "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), null, "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), " ", "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", null, int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", " ", int.class)); assertViolatesPrecondition( () -> selectNestedMethod(List.of("ClassName"), "ClassName", "methodName", (Class) null)); assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", "methodName", new Class[] { int.class, null })); } /** * @since 1.10 */ @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClasses, nestedClass, methodName, parameterTypes)") void selectNestedMethodByEnclosingClassesClassMethodNameAndParameterTypesPreconditions() { List> enclosingClassList = List.of(ClassWithNestedInnerClass.class); Class nestedClass = ClassWithNestedInnerClass.NestedClass.class; assertViolatesPrecondition(() -> selectNestedMethod(null, nestedClass, "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(List.of(), nestedClass, "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(enclosingClassList, null, "methodName", int.class)); assertViolatesPrecondition(() -> selectNestedMethod(enclosingClassList, nestedClass, null, int.class)); assertViolatesPrecondition(() -> selectNestedMethod(enclosingClassList, nestedClass, " ", int.class)); assertViolatesPrecondition( () -> selectNestedMethod(enclosingClassList, nestedClass, "methodName", (Class) null)); assertViolatesPrecondition(() -> selectNestedMethod(enclosingClassList, nestedClass, "methodName", new Class[] { int.class, null })); } static class ClassWithNestedInnerClass { // @Nested class NestedClass { // @Test void nestedTest() { } // @Test void nestedTest(String parameter) { } // @Nested class DoubleNestedClass { // @Test void doubleNestedTest() { } } } } } // ------------------------------------------------------------------------- private void assertViolatesPrecondition(Executable precondition) { assertThrows(PreconditionViolationException.class, precondition); } private static String fqmn(Class... params) { return fqmn(DiscoverySelectorsTests.class, "myTest", params); } private static String fqmn(Class clazz, String methodName, Class... params) { return ReflectionUtils.getFullyQualifiedMethodName(clazz, methodName, params); } private static String fqmnWithParamNames(String... params) { return String.format("%s#%s(%s)", DiscoverySelectorsTests.class.getName(), "myTest", join(", ", params)); } interface TestInterface { @Test default void myTest() { } } private static class TestCaseWithDefaultMethod implements TestInterface { } void myTest() { } void myTest(int num) { } void myTest(int[] nums) { } void myTest(int[][] grid) { } void myTest(int[][][][][] grid) { } void myTest(String info) { } void myTest(String info, boolean[] flags) { } void myTest(String[] info) { } void myTest(String[][] info) { } void myTest(Double[][][][][] data) { } } FilePositionTests.java000066400000000000000000000073301455764576500341400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link FilePosition}. * * @since 1.7 */ @DisplayName("FilePosition unit tests") class FilePositionTests extends AbstractEqualsAndHashCodeTests { @Test @DisplayName("factory method preconditions") void preconditions() { assertThrows(PreconditionViolationException.class, () -> FilePosition.from(-1)); assertThrows(PreconditionViolationException.class, () -> FilePosition.from(0, -1)); } @Test @DisplayName("create FilePosition from factory method with line number") void filePositionFromLine() { var filePosition = FilePosition.from(42); assertThat(filePosition.getLine()).isEqualTo(42); assertThat(filePosition.getColumn()).isEmpty(); } @Test @DisplayName("create FilePosition from factory method with line number and column number") void filePositionFromLineAndColumn() { var filePosition = FilePosition.from(42, 99); assertThat(filePosition.getLine()).isEqualTo(42); assertThat(filePosition.getColumn()).contains(99); } /** * @since 1.3 */ @ParameterizedTest @MethodSource void filePositionFromQuery(String query, int expectedLine, int expectedColumn) { var optionalFilePosition = FilePosition.fromQuery(query); if (optionalFilePosition.isPresent()) { var filePosition = optionalFilePosition.get(); assertThat(filePosition.getLine()).isEqualTo(expectedLine); assertThat(filePosition.getColumn().orElse(-1)).isEqualTo(expectedColumn); } else { assertEquals(-1, expectedColumn); assertEquals(-1, expectedLine); } } @SuppressWarnings("unused") static Stream filePositionFromQuery() { return Stream.of( // arguments(null, -1, -1), // arguments("?!", -1, -1), // arguments("line=ZZ", -1, -1), // arguments("line=42", 42, -1), // arguments("line=42&column=99", 42, 99), // arguments("line=42&column=ZZ", 42, -1), // arguments("line=42&abc=xyz&column=99", 42, 99), // arguments("1=3&foo=X&line=42&abc=xyz&column=99&enigma=393939", 42, 99), // // First one wins: arguments("line=42&line=555", 42, -1), // arguments("line=42&line=555&column=99&column=555", 42, 99) // ); } @Test @DisplayName("equals() and hashCode() with column number cached by Integer.valueOf()") void equalsAndHashCode() { var same = FilePosition.from(42, 99); var sameSame = FilePosition.from(42, 99); var different = FilePosition.from(1, 2); assertEqualsAndHashCode(same, sameSame, different); } @Test @DisplayName("equals() and hashCode() with column number not cached by Integer.valueOf()") void equalsAndHashCodeWithColumnNumberNotCachedByJavaLangIntegerDotValueOf() { var same = FilePosition.from(42, 99999); var sameSame = FilePosition.from(42, 99999); var different = FilePosition.from(1, 2); assertEqualsAndHashCode(same, sameSame, different); } } FileSelectorTests.java000066400000000000000000000023501455764576500341110ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link FileSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class FileSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new FileSelector("/example/foo.txt", null); var selector2 = new FileSelector("/example/foo.txt", null); var selector3 = new FileSelector("/example/bar.txt", null); assertEqualsAndHashCode(selector1, selector2, selector3); } @Test void equalsAndHashCodeWithFilePosition() { var selector1 = new FileSelector("/example/foo.txt", FilePosition.from(1)); var selector2 = new FileSelector("/example/foo.txt", FilePosition.from(1)); var selector3 = new FileSelector("/example/bar.txt", FilePosition.from(2)); assertEqualsAndHashCode(selector1, selector2, selector3); } } MethodSelectorTests.java000066400000000000000000000072521455764576500344600ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link MethodSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class MethodSelectorTests extends AbstractEqualsAndHashCodeTests { private static final String TEST_CASE_NAME = TestCase.class.getName(); @Test void equalsAndHashCode() { var selector1 = new MethodSelector(null, TEST_CASE_NAME, "method", "int, boolean"); var selector2 = new MethodSelector(null, TEST_CASE_NAME, "method", "int, boolean"); var selector3 = new MethodSelector(TestCase.class, "method", "int, boolean"); var selector4 = new MethodSelector(TestCase.class, "method", int.class, boolean.class); Stream.of(selector2, selector3, selector4).forEach(selector -> { assertEqualsAndHashCode(selector1, selector, new MethodSelector(null, TEST_CASE_NAME, "method", "int")); assertEqualsAndHashCode(selector1, selector, new MethodSelector((ClassLoader) null, TEST_CASE_NAME, "method", "")); assertEqualsAndHashCode(selector1, selector, new MethodSelector(null, TEST_CASE_NAME, "X", "int, boolean")); assertEqualsAndHashCode(selector1, selector, new MethodSelector((ClassLoader) null, TEST_CASE_NAME, "X", "")); assertEqualsAndHashCode(selector1, selector, new MethodSelector(null, "X", "method", "int, boolean")); assertEqualsAndHashCode(selector1, selector, new MethodSelector((ClassLoader) null, "X", "method", "")); }); } @Test void preservesOriginalExceptionWhenTryingToLoadJavaClass() { var selector = new MethodSelector((ClassLoader) null, "org.example.BogusClass", "method", "int, boolean"); assertThat(selector.getClassName()).isEqualTo("org.example.BogusClass"); assertThat(selector.getMethodName()).isEqualTo("method"); assertThat(selector.getParameterTypeNames()).isEqualTo("int, boolean"); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(selector::getJavaClass)// .withMessage("Could not load class with name: org.example.BogusClass")// .withCauseInstanceOf(ClassNotFoundException.class); } @Test void preservesOriginalExceptionWhenTryingToLoadClassForParameterType() { var selector = new MethodSelector((ClassLoader) null, TEST_CASE_NAME, "method", "int[], org.example.Bogus"); assertThat(selector.getClassName()).isEqualTo(TEST_CASE_NAME); assertThat(selector.getMethodName()).isEqualTo("method"); assertThat(selector.getParameterTypeNames()).isEqualTo("int[], org.example.Bogus"); assertThatExceptionOfType(JUnitException.class)// .isThrownBy(selector::getJavaMethod)// .withMessage("Failed to load parameter type [org.example.Bogus] for method [method] in class [%s].", TEST_CASE_NAME)// .withCauseInstanceOf(ClassNotFoundException.class); } @Test void usesClassClassLoader() { var selector = new MethodSelector(getClass(), "usesClassClassLoader", ""); assertThat(selector.getClassLoader()).isNotNull().isSameAs(getClass().getClassLoader()); } private static class TestCase { @SuppressWarnings("unused") void method(int num, boolean flag) { } } } ModuleSelectorTests.java000066400000000000000000000015501455764576500344600ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link ModuleSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class ModuleSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new ModuleSelector("foo-api"); var selector2 = new ModuleSelector("foo-api"); var selector3 = new ModuleSelector("bar-impl"); assertEqualsAndHashCode(selector1, selector2, selector3); } } NestedClassSelectorTests.java000066400000000000000000000047031455764576500354460ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link NestedClassSelector}. * * @since 1.6 * @see DiscoverySelectorsTests */ class NestedClassSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new NestedClassSelector(null, List.of("org.example.EnclosingTestClass"), "org.example.NestedTestClass"); var selector2 = new NestedClassSelector(null, List.of("org.example.EnclosingTestClass"), "org.example.NestedTestClass"); var selector3 = new NestedClassSelector(null, List.of("org.example.X"), "org.example.Y"); assertEqualsAndHashCode(selector1, selector2, selector3); } @Test void preservesOriginalExceptionWhenTryingToLoadEnclosingClasses() { var selector = new NestedClassSelector(null, List.of("org.example.EnclosingTestClass"), "org.example.NestedTestClass"); var exception = assertThrows(PreconditionViolationException.class, selector::getEnclosingClasses); assertThat(exception).hasMessage("Could not load class with name: org.example.EnclosingTestClass") // .hasCauseInstanceOf(ClassNotFoundException.class); } @Test void preservesOriginalExceptionWhenTryingToLoadNestedClass() { var selector = new NestedClassSelector(null, List.of("org.example.EnclosingTestClass"), "org.example.NestedTestClass"); var exception = assertThrows(PreconditionViolationException.class, selector::getNestedClass); assertThat(exception).hasMessage("Could not load class with name: org.example.NestedTestClass") // .hasCauseInstanceOf(ClassNotFoundException.class); } @Test void usesClassClassLoader() { var selector = new NestedClassSelector(List.of(getClass()), NestedTestCase.class); assertThat(selector.getClassLoader()).isNotNull().isSameAs(getClass().getClassLoader()); } @SuppressWarnings("InnerClassMayBeStatic") class NestedTestCase { } } NestedMethodSelectorTests.java000066400000000000000000000066301455764576500356220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link NestedMethodSelector}. * * @since 1.6 * @see DiscoverySelectorsTests */ class NestedMethodSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "int, boolean"); var selector2 = new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "int, boolean"); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("X"), "NestedTestClass", "method", "int, boolean")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("X"), "NestedTestClass", "method", "")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "int")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "X", "int, boolean")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "X", "")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "X", "method", "int, boolean")); assertEqualsAndHashCode(selector1, selector2, new NestedMethodSelector(null, List.of("EnclosingClass"), "X", "method", "")); } @Test void preservesOriginalExceptionWhenTryingToLoadEnclosingClass() { var selector = new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "int, boolean"); var exception = assertThrows(PreconditionViolationException.class, selector::getEnclosingClasses); assertThat(exception).hasMessage("Could not load class with name: EnclosingClass") // .hasCauseInstanceOf(ClassNotFoundException.class); } @Test void preservesOriginalExceptionWhenTryingToLoadNestedClass() { var selector = new NestedMethodSelector(null, List.of("EnclosingClass"), "NestedTestClass", "method", "int, boolean"); var exception = assertThrows(PreconditionViolationException.class, selector::getNestedClass); assertThat(exception).hasMessage("Could not load class with name: NestedTestClass") // .hasCauseInstanceOf(ClassNotFoundException.class); } @Test void usesClassClassLoader() { var selector = new NestedMethodSelector(List.of(getClass()), NestedTestCase.class, "method", ""); assertThat(selector.getClassLoader()).isNotNull().isSameAs(getClass().getClassLoader()); } @SuppressWarnings("InnerClassMayBeStatic") class NestedTestCase { void method() { } } } PackageNameFilterTests.java000066400000000000000000000140011455764576500350270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * @since 1.0 */ class PackageNameFilterTests { @Test void includePackageChecksPreconditions() { assertThatThrownBy(() -> PackageNameFilter.includePackageNames((String[]) null)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames array must not be null or empty"); assertThatThrownBy(() -> PackageNameFilter.includePackageNames(new String[0])) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames array must not be null or empty"); assertThatThrownBy(() -> PackageNameFilter.includePackageNames(new String[] { null })) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames array must not contain null elements"); } @Test void includePackageWithMultiplePackages() { var includedPackage1 = "java.lang"; var includedPackage2 = "java.util"; var filter = PackageNameFilter.includePackageNames(includedPackage1, includedPackage2); assertThat(filter).hasToString( "IncludePackageNameFilter that includes packages whose names are either equal to or start with one of the following: '" + includedPackage1 + "' OR '" + includedPackage2 + "'"); assertTrue(filter.apply("java.lang.String").included()); assertTrue(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Package name [java.lang.String] matches included name: '" + includedPackage1 + "'"); assertTrue(filter.apply("java.util.Collection").included()); assertTrue(filter.toPredicate().test("java.util.Collection")); assertThat(filter.apply("java.util.Collection").getReason()).contains( "Package name [java.util.Collection] matches included name: '" + includedPackage2 + "'"); assertTrue(filter.apply("java.util.function.Consumer").included()); assertTrue(filter.toPredicate().test("java.util.function.Consumer")); assertThat(filter.apply("java.util.function.Consumer").getReason()).contains( "Package name [java.util.function.Consumer] matches included name: '" + includedPackage2 + "'"); assertFalse(filter.apply("java.time.Instant").included()); assertFalse(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Package name [java.time.Instant] does not match any included names: '" + includedPackage1 + "' OR '" + includedPackage2 + "'"); assertFalse(filter.apply("java.language.Test").included()); assertFalse(filter.toPredicate().test("java.language.Test")); assertThat(filter.apply("java.language.Test").getReason()).contains( "Package name [java.language.Test] does not match any included names: '" + includedPackage1 + "' OR '" + includedPackage2 + "'"); } @Test void excludePackageChecksPreconditions() { assertThatThrownBy(() -> PackageNameFilter.excludePackageNames((String[]) null)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames must not be null or empty"); assertThatThrownBy(() -> PackageNameFilter.excludePackageNames(new String[0])) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames must not be null or empty"); assertThatThrownBy(() -> PackageNameFilter.excludePackageNames(new String[] { null })) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage("packageNames must not contain null elements"); } @Test void excludePackageWithMultiplePackages() { var excludedPackage1 = "java.lang"; var excludedPackage2 = "java.util"; var filter = PackageNameFilter.excludePackageNames(excludedPackage1, excludedPackage2); assertThat(filter).hasToString( "ExcludePackageNameFilter that excludes packages whose names are either equal to or start with one of the following: '" + excludedPackage1 + "' OR '" + excludedPackage2 + "'"); assertTrue(filter.apply("java.lang.String").excluded()); assertFalse(filter.toPredicate().test("java.lang.String")); assertThat(filter.apply("java.lang.String").getReason()).contains( "Package name [java.lang.String] matches excluded name: '" + excludedPackage1 + "'"); assertTrue(filter.apply("java.util.Collection").excluded()); assertFalse(filter.toPredicate().test("java.util.Collection")); assertThat(filter.apply("java.util.Collection").getReason()).contains( "Package name [java.util.Collection] matches excluded name: '" + excludedPackage2 + "'"); assertTrue(filter.apply("java.util.function.Consumer").excluded()); assertFalse(filter.toPredicate().test("java.util.function.Consumer")); assertThat(filter.apply("java.util.function.Consumer").getReason()).contains( "Package name [java.util.function.Consumer] matches excluded name: '" + excludedPackage2 + "'"); assertTrue(filter.apply("java.time.Instant").included()); assertTrue(filter.toPredicate().test("java.time.Instant")); assertThat(filter.apply("java.time.Instant").getReason()).contains( "Package name [java.time.Instant] does not match any excluded names: '" + excludedPackage1 + "' OR '" + excludedPackage2 + "'"); assertTrue(filter.apply("java.language.Test").included()); assertTrue(filter.toPredicate().test("java.language.Test")); assertThat(filter.apply("java.language.Test").getReason()).contains( "Package name [java.language.Test] does not match any excluded names: '" + excludedPackage1 + "' OR '" + excludedPackage2 + "'"); } } PackageSelectorTests.java000066400000000000000000000016041455764576500345660ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link PackageSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class PackageSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var selector1 = new PackageSelector("org.example.foo"); var selector2 = new PackageSelector("org.example.foo"); var selector3 = new PackageSelector("org.example.bar"); assertEqualsAndHashCode(selector1, selector2, selector3); } } UniqueIdSelectorTests.java000066400000000000000000000021341455764576500347550ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.engine.UniqueId; /** * Unit tests for {@link UniqueIdSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class UniqueIdSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() { var testEngine = UniqueId.forEngine("test-engine"); var selector1 = new UniqueIdSelector(testEngine.append("test-class", "org.example.TestClass")); var selector2 = new UniqueIdSelector(testEngine.append("test-class", "org.example.TestClass")); var selector3 = new UniqueIdSelector(testEngine.append("test-class", "org.example.FooBar")); assertEqualsAndHashCode(selector1, selector2, selector3); } } UriSelectorTests.java000066400000000000000000000016721455764576500337770ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.discovery; import java.net.URI; import org.junit.jupiter.api.Test; import org.junit.platform.AbstractEqualsAndHashCodeTests; /** * Unit tests for {@link UriSelector}. * * @since 1.3 * @see DiscoverySelectorsTests */ class UriSelectorTests extends AbstractEqualsAndHashCodeTests { @Test void equalsAndHashCode() throws Exception { var selector1 = new UriSelector(new URI("https://junit.org")); var selector2 = new UriSelector(new URI("https://junit.org")); var selector3 = new UriSelector(new URI("https://example.org")); assertEqualsAndHashCode(selector1, selector2, selector3); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/000077500000000000000000000000001455764576500274275ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/config/000077500000000000000000000000001455764576500306745ustar00rootroot00000000000000PrefixedConfigurationParametersTests.java000066400000000000000000000055221455764576500410310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/config/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.config; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Optional; import java.util.function.Function; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; /** * Unit tests for {@link PrefixedConfigurationParameters}. * * @since 1.3 */ @ExtendWith(MockitoExtension.class) class PrefixedConfigurationParametersTests { @Mock private ConfigurationParameters delegate; @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> new PrefixedConfigurationParameters(null, "example.")); assertThrows(PreconditionViolationException.class, () -> new PrefixedConfigurationParameters(delegate, null)); assertThrows(PreconditionViolationException.class, () -> new PrefixedConfigurationParameters(delegate, "")); assertThrows(PreconditionViolationException.class, () -> new PrefixedConfigurationParameters(delegate, " ")); } @Test void delegatesGetCalls() { when(delegate.get(any())).thenReturn(Optional.of("result")); var parameters = new PrefixedConfigurationParameters(delegate, "foo.bar."); assertThat(parameters.get("qux")).contains("result"); verify(delegate).get("foo.bar.qux"); } @Test void delegatesGetBooleanCalls() { when(delegate.getBoolean(any())).thenReturn(Optional.of(true)); var parameters = new PrefixedConfigurationParameters(delegate, "foo.bar."); assertThat(parameters.getBoolean("qux")).contains(true); verify(delegate).getBoolean("foo.bar.qux"); } @Test void delegatesGetWithTransformerCalls() { when(delegate.get(any(), any())).thenReturn(Optional.of("QUX")); var parameters = new PrefixedConfigurationParameters(delegate, "foo.bar."); Function transformer = String::toUpperCase; assertThat(parameters.get("qux", transformer)).contains("QUX"); verify(delegate).get("foo.bar.qux", transformer); } @Test @SuppressWarnings("deprecation") void delegatesSizeCalls() { when(delegate.size()).thenReturn(42); var parameters = new PrefixedConfigurationParameters(delegate, "foo.bar."); assertThat(parameters.size()).isEqualTo(42); verify(delegate).size(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/000077500000000000000000000000001455764576500316055ustar00rootroot00000000000000AbstractTestDescriptorTests.java000066400000000000000000000134171455764576500400640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; /** * Unit tests for {@link AbstractTestDescriptor} and {@link EngineDescriptor}. * * @since 1.0 */ class AbstractTestDescriptorTests { private EngineDescriptor engineDescriptor; private GroupDescriptor group1; private GroupDescriptor group11; private LeafDescriptor leaf111; @BeforeEach void initTree() { engineDescriptor = new EngineDescriptor(UniqueId.forEngine("testEngine"), "testEngine"); group1 = new GroupDescriptor(UniqueId.root("group", "group1")); engineDescriptor.addChild(group1); var group2 = new GroupDescriptor(UniqueId.root("group", "group2")); engineDescriptor.addChild(group2); group11 = new GroupDescriptor(UniqueId.root("group", "group1-1")); group1.addChild(group11); group1.addChild(new LeafDescriptor(UniqueId.root("leaf", "leaf1-1"))); group1.addChild(new LeafDescriptor(UniqueId.root("leaf", "leaf1-2"))); group2.addChild(new LeafDescriptor(UniqueId.root("leaf", "leaf2-1"))); leaf111 = new LeafDescriptor(UniqueId.root("leaf", "leaf11-1")); group11.addChild(leaf111); } @Test void removeRootFromHierarchyFails() { var e = assertThrows(JUnitException.class, () -> engineDescriptor.removeFromHierarchy()); assertTrue(e.toString().contains("cannot remove the root of a hierarchy")); } @Test void removeFromHierarchyClearsParentFromAllChildren() { var group = engineDescriptor.getChildren().iterator().next(); assertSame(engineDescriptor, group.getParent().orElseThrow(Error::new)); assertTrue(group.getChildren().stream().allMatch(d -> d.getParent().orElseThrow(Error::new) == group)); var formerChildren = group.getChildren(); group.removeFromHierarchy(); assertFalse(group.getParent().isPresent()); assertTrue(group.getChildren().isEmpty()); assertTrue(formerChildren.stream().noneMatch(d -> d.getParent().isPresent())); } @Test void setParentToOtherInstance() { TestDescriptor newEngine = new EngineDescriptor(UniqueId.forEngine("newEngine"), "newEngine"); var group = engineDescriptor.getChildren().iterator().next(); assertSame(engineDescriptor, group.getParent().orElseThrow(Error::new)); group.setParent(newEngine); assertSame(newEngine, group.getParent().orElseThrow(Error::new)); } @Test void setParentToNull() { var group = engineDescriptor.getChildren().iterator().next(); assertTrue(group.getParent().isPresent()); group.setParent(null); assertFalse(group.getParent().isPresent()); } @Test void visitAllNodes() { List visited = new ArrayList<>(); engineDescriptor.accept(visited::add); assertEquals(8, visited.size()); } @Test void pruneLeaf() { TestDescriptor.Visitor visitor = descriptor -> { if (descriptor.getUniqueId().equals(UniqueId.root("leaf", "leaf1-1"))) descriptor.removeFromHierarchy(); }; engineDescriptor.accept(visitor); List visited = new ArrayList<>(); engineDescriptor.accept(descriptor -> visited.add(descriptor.getUniqueId())); assertEquals(7, visited.size()); assertTrue(visited.contains(UniqueId.root("group", "group1"))); assertFalse(visited.contains(UniqueId.root("leaf", "leaf1-1"))); } @Test void pruneGroup() { final var countVisited = new AtomicInteger(); TestDescriptor.Visitor visitor = descriptor -> { if (descriptor.getUniqueId().equals(UniqueId.root("group", "group1"))) descriptor.removeFromHierarchy(); countVisited.incrementAndGet(); }; engineDescriptor.accept(visitor); assertEquals(4, countVisited.get(), "Children of pruned element are not visited"); List visited = new ArrayList<>(); engineDescriptor.accept(descriptor -> visited.add(descriptor.getUniqueId())); assertEquals(3, visited.size()); assertFalse(visited.contains(UniqueId.root("group", "group1"))); } @Test void getAncestors() { assertThat(getAncestorsUniqueIds(engineDescriptor)).isEmpty(); assertThat(getAncestorsUniqueIds(group1)).containsExactly( // UniqueId.forEngine("testEngine")); assertThat(getAncestorsUniqueIds(group11)).containsExactly( // UniqueId.root("group", "group1"), // UniqueId.forEngine("testEngine")); assertThat(getAncestorsUniqueIds(leaf111)).containsExactly( // UniqueId.root("group", "group1-1"), // UniqueId.root("group", "group1"), // UniqueId.forEngine("testEngine")); } private List getAncestorsUniqueIds(TestDescriptor descriptor) { return descriptor.getAncestors().stream().map(TestDescriptor::getUniqueId).toList(); } } class GroupDescriptor extends AbstractTestDescriptor { GroupDescriptor(UniqueId uniqueId) { super(uniqueId, "group: " + uniqueId); } @Override public Type getType() { return Type.CONTAINER; } } class LeafDescriptor extends AbstractTestDescriptor { LeafDescriptor(UniqueId uniqueId) { super(uniqueId, "leaf: " + uniqueId); } @Override public Type getType() { return Type.TEST; } } AbstractTestSourceTests.java000066400000000000000000000052361455764576500372060ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.platform.AbstractEqualsAndHashCodeTests; import org.junit.platform.engine.TestSource; /** * Abstract base class for unit tests involving {@link TestSource TestSources} * and {@link FilePosition FilePositions}. * * @since 1.0 */ abstract class AbstractTestSourceTests extends AbstractEqualsAndHashCodeTests { abstract Stream createSerializableInstances() throws Exception; @TestFactory Stream assertToString() throws Exception { return createSerializableInstances() // .map(instance -> dynamicTest(instance.toString(), () -> assertToString(instance))); } private void assertToString(Object instance) { assertNotNull(instance); assertTrue(instance.toString().startsWith(instance.getClass().getSimpleName())); } @TestFactory Stream assertSerializable() throws Exception { return createSerializableInstances() // .map(instance -> dynamicTest(instance.toString(), () -> assertSerializable(instance))); } private void assertSerializable(T instance) { try { Class type = instance.getClass(); var serialized = serialize(instance); var deserialized = deserialize(serialized); assertTrue(type.isAssignableFrom(deserialized.getClass())); assertEquals(instance, deserialized); } catch (Exception e) { fail("assertSerializable failed: " + instance, e); } } private byte[] serialize(Object obj) throws Exception { var b = new ByteArrayOutputStream(); var o = new ObjectOutputStream(b); o.writeObject(obj); return b.toByteArray(); } private Object deserialize(byte[] bytes) throws Exception { var b = new ByteArrayInputStream(bytes); var o = new ObjectInputStream(b); return o.readObject(); } } ClassSourceTests.java000066400000000000000000000143611455764576500356470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link ClassSource}. * * @since 1.0 */ class ClassSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { return Stream.of( // ClassSource.from("class.source"), // ClassSource.from("class.and.position", FilePosition.from(1, 2)), // ClassSource.from(getClass()), // ClassSource.from(getClass(), FilePosition.from(1, 2)) // ); } @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> ClassSource.from((String) null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from(" ")); assertThrows(PreconditionViolationException.class, () -> ClassSource.from((String) null, null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from(" ", null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from((Class) null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from((Class) null, null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from((URI) null)); assertThrows(PreconditionViolationException.class, () -> ClassSource.from(new URI("badscheme:/com.foo.Bar"))); assertThrows(PreconditionViolationException.class, () -> ClassSource.from(new URI("class:?line=1"))); } @Test void classSourceFromName() { var testClassName = "com.unknown.mypackage.ClassByName"; var source = ClassSource.from(testClassName); assertThat(source.getClassName()).isEqualTo(testClassName); assertThat(source.getPosition()).isEmpty(); var exception = assertThrows(PreconditionViolationException.class, source::getJavaClass); assertThat(exception).hasMessage("Could not load class with name: " + testClassName); } @Test void classSourceFromNameAndFilePosition() { var testClassName = "com.unknown.mypackage.ClassByName"; var position = FilePosition.from(42, 23); var source = ClassSource.from(testClassName, position); assertThat(source.getClassName()).isEqualTo(testClassName); assertThat(source.getPosition()).isNotEmpty(); assertThat(source.getPosition()).hasValue(position); } @Test void classSourceFromReference() { var testClass = getClass(); var source = ClassSource.from(testClass); assertThat(source.getJavaClass()).isEqualTo(testClass); assertThat(source.getPosition()).isEmpty(); } @Test void classSourceFromReferenceAndFilePosition() { var testClass = getClass(); var position = FilePosition.from(42, 23); var source = ClassSource.from(testClass, position); assertThat(source.getJavaClass()).isEqualTo(testClass); assertThat(source.getPosition()).isNotEmpty(); assertThat(source.getPosition()).hasValue(position); } @Test void classSourceFromUri() throws URISyntaxException { var source = ClassSource.from(new URI("class:java.lang.Object")); assertThat(source.getJavaClass()).isEqualTo(Object.class); assertThat(source.getPosition()).isEmpty(); } @Test void classSourceFromUriWithLineNumber() throws URISyntaxException { var position = FilePosition.from(42); var source = ClassSource.from(new URI("class:java.lang.Object?line=42")); assertThat(source.getJavaClass()).isEqualTo(Object.class); assertThat(source.getPosition()).hasValue(position); } @Test void classSourceFromUriWithLineAndColumnNumbers() throws URISyntaxException { var position = FilePosition.from(42, 23); var source = ClassSource.from(new URI("class:java.lang.Object?line=42&foo=bar&column=23")); assertThat(source.getJavaClass()).isEqualTo(Object.class); assertThat(source.getPosition()).hasValue(position); } @Test void classSourceFromUriWithEmptyQuery() throws URISyntaxException { var source = ClassSource.from(new URI("class:java.lang.Object?")); assertThat(source.getJavaClass()).isEqualTo(Object.class); assertThat(source.getPosition()).isEmpty(); } @Test void classSourceFromUriWithUnsupportedParametersInQuery() throws URISyntaxException { var source = ClassSource.from(new URI("class:java.lang.Object?foo=42&bar")); assertThat(source.getJavaClass()).isEqualTo(Object.class); assertThat(source.getPosition()).isEmpty(); } @Test void equalsAndHashCodeForClassSourceFromName() { var name1 = String.class.getName(); var name2 = Number.class.getName(); assertEqualsAndHashCode(ClassSource.from(name1), ClassSource.from(name1), ClassSource.from(name2)); } @Test void equalsAndHashCodeForClassSourceFromNameAndFilePosition() { var name1 = String.class.getName(); var name2 = Number.class.getName(); var position1 = FilePosition.from(42, 23); var position2 = FilePosition.from(1, 2); assertEqualsAndHashCode(ClassSource.from(name1, position1), ClassSource.from(name1, position1), ClassSource.from(name2, position1)); assertEqualsAndHashCode(ClassSource.from(name1, position1), ClassSource.from(name1, position1), ClassSource.from(name1, position2)); } @Test void equalsAndHashCodeForClassSourceFromReference() { var class1 = String.class; var class2 = Number.class; assertEqualsAndHashCode(ClassSource.from(class1), ClassSource.from(class1), ClassSource.from(class2)); } @Test void equalsAndHashCodeForClassSourceFromReferenceAndFilePosition() { var class1 = String.class; var class2 = Number.class; var position1 = FilePosition.from(42, 23); var position2 = FilePosition.from(1, 2); assertEqualsAndHashCode(ClassSource.from(class1, position1), ClassSource.from(class1, position1), ClassSource.from(class2, position1)); assertEqualsAndHashCode(ClassSource.from(class1, position1), ClassSource.from(class1, position1), ClassSource.from(class1, position2)); } } ClasspathResourceSourceTests.java000066400000000000000000000100431455764576500402250ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.support.descriptor.ClasspathResourceSource.CLASSPATH_SCHEME; import java.net.URI; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link ClasspathResourceSource}. * * @since 1.0 */ class ClasspathResourceSourceTests extends AbstractTestSourceTests { private static final String FOO_RESOURCE = "test/foo.xml"; private static final String BAR_RESOURCE = "/config/bar.json"; private static final URI FOO_RESOURCE_URI = URI.create(CLASSPATH_SCHEME + ":/" + FOO_RESOURCE); @Override Stream createSerializableInstances() { return Stream.of(ClasspathResourceSource.from(FOO_RESOURCE)); } @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from((String) null)); assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from("")); assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from(" ")); assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from((URI) null)); assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from(URI.create("file:/foo.txt"))); } @Test void resourceWithoutPosition() { var source = ClasspathResourceSource.from(FOO_RESOURCE); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).isEmpty(); } @Test void resourceWithLeadingSlashWithoutPosition() { var source = ClasspathResourceSource.from("/" + FOO_RESOURCE); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).isEmpty(); } @Test void resourceWithPosition() { var position = FilePosition.from(42, 23); var source = ClasspathResourceSource.from(FOO_RESOURCE, position); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).hasValue(position); } @Test void resourceFromUriWithoutPosition() { var source = ClasspathResourceSource.from(FOO_RESOURCE_URI); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).isEmpty(); } @Test void resourceFromUriWithLineNumber() { var position = FilePosition.from(42); var uri = URI.create(FOO_RESOURCE_URI + "?line=42"); var source = ClasspathResourceSource.from(uri); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).hasValue(position); } @Test void resourceFromUriWithLineAndColumnNumbers() { var position = FilePosition.from(42, 23); var uri = URI.create(FOO_RESOURCE_URI + "?line=42&foo=bar&column=23"); var source = ClasspathResourceSource.from(uri); assertThat(source).isNotNull(); assertThat(source.getClasspathResourceName()).isEqualTo(FOO_RESOURCE); assertThat(source.getPosition()).hasValue(position); } @Test void equalsAndHashCode() { assertEqualsAndHashCode(ClasspathResourceSource.from(FOO_RESOURCE), ClasspathResourceSource.from(FOO_RESOURCE), ClasspathResourceSource.from(BAR_RESOURCE)); var position = FilePosition.from(42, 23); assertEqualsAndHashCode(ClasspathResourceSource.from(FOO_RESOURCE, position), ClasspathResourceSource.from(FOO_RESOURCE, position), ClasspathResourceSource.from(BAR_RESOURCE, position)); } } CompositeTestSourceTests.java000066400000000000000000000046751455764576500374130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link CompositeTestSource}. * * @since 1.0 */ class CompositeTestSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { var fileSource = FileSource.from(new File("sample.instance")); var classSource = ClassSource.from(getClass()); var sources = List.of(fileSource, classSource); return Stream.of(CompositeTestSource.from(sources)); } @Test void createCompositeTestSourceFromNullList() { assertThrows(PreconditionViolationException.class, () -> CompositeTestSource.from(null)); } @Test void createCompositeTestSourceFromEmptyList() { assertThrows(PreconditionViolationException.class, () -> CompositeTestSource.from(List.of())); } @Test void createCompositeTestSourceFromClassAndFileSources() { var fileSource = FileSource.from(new File("example.test")); var classSource = ClassSource.from(getClass()); var sources = new ArrayList<>(List.of(fileSource, classSource)); var compositeTestSource = CompositeTestSource.from(sources); assertThat(compositeTestSource.getSources()).hasSize(2); assertThat(compositeTestSource.getSources()).contains(fileSource, classSource); // Ensure the supplied sources list was defensively copied. sources.remove(1); assertThat(compositeTestSource.getSources()).hasSize(2); // Ensure the returned sources list is immutable. assertThrows(UnsupportedOperationException.class, () -> compositeTestSource.getSources().add(fileSource)); } @Test void equalsAndHashCode() { var sources1 = List.of(ClassSource.from(Number.class)); var sources2 = List.of(ClassSource.from(String.class)); assertEqualsAndHashCode(CompositeTestSource.from(sources1), CompositeTestSource.from(sources1), CompositeTestSource.from(sources2)); } } DefaultUriSourceTests.java000066400000000000000000000033101455764576500366360ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.net.URI; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link DefaultUriSource}. * * @since 1.3 */ class DefaultUriSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { return Stream.of(new DefaultUriSource(URI.create("sample://instance"))); } @Test void nullSourceUriYieldsException() { assertThrows(PreconditionViolationException.class, () -> new DefaultUriSource(null)); } @Test void getterReturnsSameUriInstanceAsSuppliedToTheConstructor() throws Exception { var expected = new URI("foo.txt"); var actual = new DefaultUriSource(expected).getUri(); assertSame(expected, actual); } @Test void equalsAndHashCode() throws Exception { var uri1 = new URI("foo.txt"); var uri2 = new URI("bar.txt"); assertEqualsAndHashCode(new DefaultUriSource(uri1), new DefaultUriSource(uri1), new DefaultUriSource(uri2)); } @Test void testToString() { var actual = new DefaultUriSource(URI.create("foo.txt")).toString(); assertEquals("DefaultUriSource [uri = foo.txt]", actual); } } DemoClassTestDescriptor.java000066400000000000000000000044621455764576500371500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static java.util.stream.Collectors.toCollection; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import java.util.LinkedHashSet; import java.util.Set; import org.junit.jupiter.api.Tag; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; /** * @since 1.0 */ public class DemoClassTestDescriptor extends AbstractTestDescriptor { private static final Logger logger = LoggerFactory.getLogger(DemoClassTestDescriptor.class); private final Class testClass; public DemoClassTestDescriptor(UniqueId uniqueId, Class testClass) { super(uniqueId, Preconditions.notNull(testClass, "Class must not be null").getSimpleName(), ClassSource.from(testClass)); this.testClass = testClass; } @Override public Set getTags() { // Copied from org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.getTags(AnnotatedElement) // @formatter:off return findRepeatableAnnotations(this.testClass, Tag.class).stream() .map(Tag::value) .filter(tag -> { var isValid = TestTag.isValid(tag); if (!isValid) { // TODO [#242] Replace logging with precondition check once we have a proper mechanism for // handling validation exceptions during the TestEngine discovery phase. // // As an alternative to a precondition check here, we could catch any // PreconditionViolationException thrown by TestTag::create. logger.warn(() -> String.format( "Configuration error: invalid tag syntax in @Tag(\"%s\") declaration on [%s]. Tag will be ignored.", tag, this.testClass)); } return isValid; }) .map(TestTag::create) .collect(toCollection(LinkedHashSet::new)); // @formatter:on } @Override public Type getType() { return Type.CONTAINER; } } DemoMethodTestDescriptor.java000066400000000000000000000056151455764576500373240ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static java.util.stream.Collectors.toCollection; import static org.junit.platform.commons.util.AnnotationUtils.findRepeatableAnnotations; import java.lang.reflect.Method; import java.util.LinkedHashSet; import java.util.Set; import org.junit.jupiter.api.Tag; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; /** * @since 1.0 */ public class DemoMethodTestDescriptor extends AbstractTestDescriptor { private static final Logger logger = LoggerFactory.getLogger(DemoMethodTestDescriptor.class); private final Class testClass; private final Method testMethod; public DemoMethodTestDescriptor(UniqueId uniqueId, Class testClass, Method testMethod) { super(uniqueId, String.format("%s(%s)", Preconditions.notNull(testMethod, "Method must not be null").getName(), ClassUtils.nullSafeToString(Class::getSimpleName, testMethod.getParameterTypes())), MethodSource.from(testMethod)); this.testClass = Preconditions.notNull(testClass, "Class must not be null"); this.testMethod = testMethod; } @Override public Set getTags() { // Copied from org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.getTags(AnnotatedElement) // @formatter:off Set methodTags = findRepeatableAnnotations(this.testMethod, Tag.class).stream() .map(Tag::value) .filter(tag -> { var isValid = TestTag.isValid(tag); if (!isValid) { // TODO [#242] Replace logging with precondition check once we have a proper mechanism for // handling validation exceptions during the TestEngine discovery phase. // // As an alternative to a precondition check here, we could catch any // PreconditionViolationException thrown by TestTag::create. logger.warn(() -> String.format( "Configuration error: invalid tag syntax in @Tag(\"%s\") declaration on [%s]. Tag will be ignored.", tag, this.testMethod)); } return isValid; }) .map(TestTag::create) .collect(toCollection(LinkedHashSet::new)); // @formatter:on getParent().ifPresent(parentDescriptor -> methodTags.addAll(parentDescriptor.getTags())); return methodTags; } public final Class getTestClass() { return this.testClass; } public final Method getTestMethod() { return this.testMethod; } @Override public Type getType() { return Type.TEST; } } FilePositionTests.java000066400000000000000000000074241455764576500360270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link FilePosition}. * * @since 1.0 */ @DisplayName("FilePosition unit tests") class FilePositionTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { return Stream.of(FilePosition.from(42, 99)); } @Test @DisplayName("factory method preconditions") void preconditions() { assertThrows(PreconditionViolationException.class, () -> FilePosition.from(-1)); assertThrows(PreconditionViolationException.class, () -> FilePosition.from(0, -1)); } @Test @DisplayName("create FilePosition from factory method with line number") void filePositionFromLine() { var filePosition = FilePosition.from(42); assertThat(filePosition.getLine()).isEqualTo(42); assertThat(filePosition.getColumn()).isEmpty(); } @Test @DisplayName("create FilePosition from factory method with line number and column number") void filePositionFromLineAndColumn() { var filePosition = FilePosition.from(42, 99); assertThat(filePosition.getLine()).isEqualTo(42); assertThat(filePosition.getColumn()).contains(99); } /** * @since 1.3 */ @ParameterizedTest @MethodSource void filePositionFromQuery(String query, int expectedLine, int expectedColumn) { var optionalFilePosition = FilePosition.fromQuery(query); if (optionalFilePosition.isPresent()) { var filePosition = optionalFilePosition.get(); assertThat(filePosition.getLine()).isEqualTo(expectedLine); assertThat(filePosition.getColumn().orElse(-1)).isEqualTo(expectedColumn); } else { assertEquals(-1, expectedColumn); assertEquals(-1, expectedLine); } } @SuppressWarnings("unused") static Stream filePositionFromQuery() { return Stream.of( // arguments(null, -1, -1), // arguments("?!", -1, -1), // arguments("line=ZZ", -1, -1), // arguments("line=42", 42, -1), // arguments("line=42&column=99", 42, 99), // arguments("line=42&column=ZZ", 42, -1), // arguments("line=42&abc=xyz&column=99", 42, 99), // arguments("1=3&foo=X&line=42&abc=xyz&column=99&enigma=393939", 42, 99), // // First one wins: arguments("line=42&line=555", 42, -1), // arguments("line=42&line=555&column=99&column=555", 42, 99) // ); } @Test @DisplayName("equals() and hashCode() with column number cached by Integer.valueOf()") void equalsAndHashCode() { var same = FilePosition.from(42, 99); var sameSame = FilePosition.from(42, 99); var different = FilePosition.from(1, 2); assertEqualsAndHashCode(same, sameSame, different); } @Test @DisplayName("equals() and hashCode() with column number not cached by Integer.valueOf()") void equalsAndHashCodeWithColumnNumberNotCachedByJavaLangIntegerDotValueOf() { var same = FilePosition.from(42, 99999); var sameSame = FilePosition.from(42, 99999); var different = FilePosition.from(1, 2); assertEqualsAndHashCode(same, sameSame, different); } } FileSystemSourceTests.java000066400000000000000000000056441455764576500366720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link FileSource} and {@link DirectorySource}. * * @since 1.0 */ class FileSystemSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { return Stream.of( // FileSource.from(new File("file.source")), // FileSource.from(new File("file.and.position"), FilePosition.from(42, 23))); } @Test void nullSourceFileOrDirectoryYieldsException() { assertThrows(PreconditionViolationException.class, () -> FileSource.from(null)); } @Test void directory() throws Exception { var canonicalDir = new File(".").getCanonicalFile(); var relativeDir = new File("..", canonicalDir.getName()); var source = DirectorySource.from(relativeDir); assertThat(source.getUri()).isEqualTo(canonicalDir.toURI()); assertThat(source.getFile()).isEqualTo(canonicalDir); } @Test void fileWithoutPosition() throws Exception { var canonicalDir = new File(".").getCanonicalFile(); var relativeDir = new File("..", canonicalDir.getName()); var relativeFile = new File(relativeDir, "test.txt"); var canonicalFile = relativeFile.getCanonicalFile(); var source = FileSource.from(relativeFile); assertThat(source.getUri()).isEqualTo(canonicalFile.toURI()); assertThat(source.getFile()).isEqualTo(canonicalFile); assertThat(source.getPosition()).isEmpty(); } @Test void fileWithPosition() { var file = new File("test.txt"); var position = FilePosition.from(42, 23); var source = FileSource.from(file, position); assertThat(source.getUri()).isEqualTo(file.getAbsoluteFile().toURI()); assertThat(source.getFile()).isEqualTo(file.getAbsoluteFile()); assertThat(source.getPosition()).hasValue(position); } @Test void equalsAndHashCodeForFileSource() { var file1 = new File("foo.txt"); var file2 = new File("bar.txt"); assertEqualsAndHashCode(FileSource.from(file1), FileSource.from(file1), FileSource.from(file2)); var position = FilePosition.from(42, 23); assertEqualsAndHashCode(FileSource.from(file1, position), FileSource.from(file1, position), FileSource.from(file2, position)); } @Test void equalsAndHashCodeForDirectorySource() { var dir1 = new File("."); var dir2 = new File(".."); assertEqualsAndHashCode(DirectorySource.from(dir1), DirectorySource.from(dir1), DirectorySource.from(dir2)); } } MethodSourceTests.java000066400000000000000000000241171455764576500360220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.Serializable; import java.lang.reflect.Method; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link MethodSource}. * * @since 1.0 */ class MethodSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() throws Exception { return Stream.of( // MethodSource.from(getMethod("method1")), // MethodSource.from(getMethod("method2")) // ); } @Test void methodSource() throws Exception { var testMethod = getMethod("method1"); var source = MethodSource.from(testMethod); assertThat(source.getClassName()).isEqualTo(getClass().getName()); assertThat(source.getMethodName()).isEqualTo(testMethod.getName()); assertThat(source.getMethodParameterTypes()).isEqualTo(String.class.getName()); assertThat(source.getJavaClass()).isEqualTo(getClass()); assertThat(source.getJavaMethod()).isEqualTo(testMethod); } @Test void equalsAndHashCodeForMethodSource() throws Exception { var method1 = getMethod("method1"); var method2 = getMethod("method2"); assertEqualsAndHashCode(MethodSource.from(method1), MethodSource.from(method1), MethodSource.from(method2)); } @Test void instantiatingWithNullNamesShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from("foo", null)); assertThrows(PreconditionViolationException.class, () -> MethodSource.from(null, "foo")); } @Test void instantiatingWithEmptyNamesShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from("foo", "")); assertThrows(PreconditionViolationException.class, () -> MethodSource.from("", "foo")); } @Test void instantiatingWithBlankNamesShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from("foo", " ")); assertThrows(PreconditionViolationException.class, () -> MethodSource.from(" ", "foo")); } @Test void instantiationWithNullMethodShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from(null)); } @Test void instantiationWithNullClassOrMethodShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from(null, String.class.getDeclaredMethod("getBytes"))); assertThrows(PreconditionViolationException.class, () -> MethodSource.from(String.class, null)); } @Test void instantiationWithClassAndMethodShouldResultInACorrectObject() throws Exception { var source = MethodSource.from(String.class, String.class.getDeclaredMethod("lastIndexOf", String.class, int.class)); assertEquals(String.class.getName(), source.getClassName()); assertEquals("lastIndexOf", source.getMethodName()); assertEquals("java.lang.String, int", source.getMethodParameterTypes()); } @Test void instantiationWithClassAndMethodAsStringAndParamsAsClassVarargsShouldResultInACorrectObject() { var source = MethodSource.from(String.class.getName(), "lastIndexOf", String.class, int.class); assertEquals(String.class.getName(), source.getClassName()); assertEquals("lastIndexOf", source.getMethodName()); assertEquals("java.lang.String, int", source.getMethodParameterTypes()); } @Test void twoEqualMethodsShouldHaveEqualMethodSourceObjects() { assertEquals(MethodSource.from("TestClass1", "testMethod1"), MethodSource.from("TestClass1", "testMethod1")); } @Test void twoUnequalMethodsShouldHaveUnequalMethodSourceObjects() { assertNotEquals(MethodSource.from("TestClass1", "testMethod1"), MethodSource.from("TestClass2", "testMethod1")); } @Test void twoUnequalMethodsInTheSameClassShouldHaveUnequalMethodSourceObjects() { assertNotEquals(MethodSource.from("TestClass1", "testMethod1"), MethodSource.from("TestClass1", "testMethod2")); } @Test void twoEqualMethodSourceObjectsShouldHaveEqualHashCodes() { assertEquals(MethodSource.from("TestClass1", "testMethod1").hashCode(), MethodSource.from("TestClass1", "testMethod1").hashCode()); } @Test void twoEqualMethodsWithEqualParametersShouldHaveEqualMethodSourceObjects() { assertEquals(MethodSource.from("TestClass1", "testMethod1", "int, String"), MethodSource.from("TestClass1", "testMethod1", "int, String")); } @Test void twoUnequalMethodsWithEqualParametersShouldHaveUnequalMethodSourceObjects() { assertNotEquals(MethodSource.from("TestClass1", "testMethod1", "int, String"), MethodSource.from("TestClass1", "testMethod2", "int, String")); } @Test void twoEqualMethodsWithUnequalParametersShouldHaveUnequalMethodSourceObjects() { assertNotEquals(MethodSource.from("TestClass1", "testMethod1", "int, String"), MethodSource.from("TestClass1", "testMethod1", "float, int, String")); } @Test void twoEqualMethodsWithEqualParametersShouldHaveEqualMethodSourceHashCodes() { assertEquals(MethodSource.from("TestClass1", "testMethod1", "int, String").hashCode(), MethodSource.from("TestClass1", "testMethod1", "int, String").hashCode()); } @Test void twoEqualMethodsWithUnequalParametersShouldHaveUnequalMethodSourceHashCodes() { assertNotEquals(MethodSource.from("TestClass1", "testMethod1", "int, String").hashCode(), MethodSource.from("TestClass1", "testMethod1", "float, int, String").hashCode()); } @Test void aReflectedMethodsClassNameShouldBeConsistent() throws Exception { var m = String.class.getDeclaredMethod("valueOf", int.class); assertEquals("java.lang.String", MethodSource.from(m).getClassName()); } @Test void aReflectedMethodsMethodNameShouldBeConsistent() throws Exception { var m = String.class.getDeclaredMethod("valueOf", int.class); assertEquals("valueOf", MethodSource.from(m).getMethodName()); } @Test void aReflectedMethodsParameterTypesShouldBeConsistent() throws Exception { var m = String.class.getDeclaredMethod("valueOf", float.class); assertEquals("float", MethodSource.from(m).getMethodParameterTypes()); } @Test void twoEqualReflectedMethodsShouldHaveEqualMethodSourceObjects() throws Exception { var m1 = String.class.getDeclaredMethod("valueOf", int.class); var m2 = String.class.getDeclaredMethod("valueOf", int.class); assertEquals(MethodSource.from(m1), MethodSource.from(m2)); } @Test void twoEqualReflectedMethodsShouldHaveEqualMethodSourceHashCodes() throws Exception { var m1 = String.class.getDeclaredMethod("valueOf", int.class); var m2 = String.class.getDeclaredMethod("valueOf", int.class); assertEquals(MethodSource.from(m1).hashCode(), MethodSource.from(m2).hashCode()); } @Test void twoUnequalReflectedMethodsShouldNotHaveEqualMethodSourceObjects() throws Exception { var m1 = String.class.getDeclaredMethod("valueOf", int.class); var m2 = Byte.class.getDeclaredMethod("byteValue"); assertNotEquals(MethodSource.from(m1), MethodSource.from(m2)); } @Test void twoUnequalReflectedMethodsShouldNotHaveEqualMethodSourceHashCodes() throws Exception { var m1 = String.class.getDeclaredMethod("valueOf", int.class); var m2 = Byte.class.getDeclaredMethod("byteValue"); assertNotEquals(MethodSource.from(m1).hashCode(), MethodSource.from(m2).hashCode()); } @Test void getJavaClassFromString() { var source = MethodSource.from(getClass().getName(), "method1"); assertThat(source.getJavaClass()).isEqualTo(getClass()); } @Test void getJavaClassShouldThrowExceptionIfClassNotFound() { var source = MethodSource.from(getClass().getName() + "X", "method1"); assertThrows(PreconditionViolationException.class, source::getJavaClass); } @Test void getJavaMethodShouldReturnGivenMethodIfOverloadExists() throws Exception { var testMethod = getMethod("method3"); var source = MethodSource.from(testMethod); assertThat(source.getJavaMethod()).isEqualTo(testMethod); } @Test void getJavaMethodFromStringShouldFindVoidMethod() throws Exception { var testMethod = getClass().getDeclaredMethod("methodVoid"); var source = MethodSource.from(getClass().getName(), testMethod.getName()); assertThat(source.getJavaMethod()).isEqualTo(testMethod); } @Test void getJavaMethodFromStringShouldFindMethodWithParameter() throws Exception { var testMethod = getClass().getDeclaredMethod("method3", Integer.TYPE); var source = MethodSource.from(getClass().getName(), testMethod.getName(), testMethod.getParameterTypes()); assertThat(source.getJavaMethod()).isEqualTo(testMethod); } @Test void getJavaMethodFromStringShouldThrowExceptionIfParameterTypesAreNotSupplied() { var source = MethodSource.from(getClass().getName(), "method3"); assertThrows(PreconditionViolationException.class, source::getJavaMethod); } @Test void getJavaMethodFromStringShouldThrowExceptionIfParameterTypesDoNotMatch() { var source = MethodSource.from(getClass().getName(), "method3", Double.TYPE); assertThrows(PreconditionViolationException.class, source::getJavaMethod); } @Test void getJavaMethodFromStringShouldThrowExceptionIfMethodDoesNotExist() { var source = MethodSource.from(getClass().getName(), "methodX"); assertThrows(PreconditionViolationException.class, source::getJavaMethod); } private Method getMethod(String name) throws Exception { return getClass().getDeclaredMethod(name, String.class); } @SuppressWarnings("unused") void method1(String text) { } @SuppressWarnings("unused") void method2(String text) { } @SuppressWarnings("unused") void method3(String text) { } @SuppressWarnings("unused") void method3(int number) { } @SuppressWarnings("unused") void methodVoid() { } } PackageSourceTests.java000066400000000000000000000037551455764576500361420ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.descriptor; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.Serializable; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; /** * Unit tests for {@link PackageSource}. * * @since 1.0 */ class PackageSourceTests extends AbstractTestSourceTests { @Override Stream createSerializableInstances() { return Stream.of(PackageSource.from("package.source")); } @Test void packageSourceFromNullPackageName() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from((String) null)); } @Test void packageSourceFromEmptyPackageName() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from(" ")); } @Test void packageSourceFromNullPackageReference() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from((Package) null)); } @Test void packageSourceFromPackageName() { var testPackage = getClass().getPackage().getName(); var source = PackageSource.from(testPackage); assertThat(source.getPackageName()).isEqualTo(testPackage); } @Test void packageSourceFromPackageReference() { var testPackage = getClass().getPackage(); var source = PackageSource.from(testPackage); assertThat(source.getPackageName()).isEqualTo(testPackage.getName()); } @Test void equalsAndHashCodeForPackageSource() { var pkg1 = getClass().getPackage(); var pkg2 = String.class.getPackage(); assertEqualsAndHashCode(PackageSource.from(pkg1), PackageSource.from(pkg1), PackageSource.from(pkg2)); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/000077500000000000000000000000001455764576500320455ustar00rootroot00000000000000CompositeLockTests.java000066400000000000000000000051401455764576500364270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.Lock; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; /** * @since 1.3 */ class CompositeLockTests { @Test @SuppressWarnings("resource") void acquiresAllLocksInOrder() throws Exception { var lock1 = mock(Lock.class); var lock2 = mock(Lock.class); new CompositeLock(List.of(lock1, lock2)).acquire(); var inOrder = inOrder(lock1, lock2); inOrder.verify(lock1).lockInterruptibly(); inOrder.verify(lock2).lockInterruptibly(); } @Test @SuppressWarnings("resource") void releasesAllLocksInReverseOrder() throws Exception { var lock1 = mock(Lock.class); var lock2 = mock(Lock.class); new CompositeLock(List.of(lock1, lock2)).acquire().close(); var inOrder = inOrder(lock1, lock2); inOrder.verify(lock2).unlock(); inOrder.verify(lock1).unlock(); } @Test @SuppressWarnings("resource") void releasesLocksInReverseOrderWhenInterruptedDuringAcquire() throws Exception { var firstTwoLocksWereLocked = new CountDownLatch(2); var firstLock = mockLock("firstLock", firstTwoLocksWereLocked::countDown); var secondLock = mockLock("secondLock", firstTwoLocksWereLocked::countDown); var unavailableLock = mockLock("unavailableLock", new CountDownLatch(1)::await); var thread = new Thread(() -> { try { new CompositeLock(List.of(firstLock, secondLock, unavailableLock)).acquire(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); thread.start(); firstTwoLocksWereLocked.await(); thread.interrupt(); thread.join(); var inOrder = inOrder(firstLock, secondLock); inOrder.verify(secondLock).unlock(); inOrder.verify(firstLock).unlock(); verify(unavailableLock, never()).unlock(); } private Lock mockLock(String name, Executable lockAction) throws InterruptedException { var lock = mock(Lock.class, name); doAnswer(invocation -> { lockAction.execute(); return null; }).when(lock).lockInterruptibly(); return lock; } } DefaultParallelExecutionConfigurationStrategyTests.java000066400000000000000000000230131455764576500450530ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.ConfigurationParameters; /** * @since 1.3 */ class DefaultParallelExecutionConfigurationStrategyTests { final ConfigurationParameters configParams = mock(); @BeforeEach void setUp() { when(configParams.get(any(), any())).thenCallRealMethod(); } @Test void fixedStrategyCreatesValidConfiguration() { when(configParams.get("fixed.parallelism")).thenReturn(Optional.of("42")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.FIXED; var configuration = strategy.createConfiguration(configParams); assertThat(configuration.getParallelism()).isEqualTo(42); assertThat(configuration.getCorePoolSize()).isEqualTo(42); assertThat(configuration.getMinimumRunnable()).isEqualTo(42); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + 42); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); assertThat(configuration.getSaturatePredicate().test(null)).isTrue(); } @Test void fixedSaturateStrategyCreatesValidConfiguration() { when(configParams.get("fixed.parallelism")).thenReturn(Optional.of("42")); when(configParams.get("fixed.max-pool-size")).thenReturn(Optional.of("42")); when(configParams.get("fixed.saturate")).thenReturn(Optional.of("false")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.FIXED; var configuration = strategy.createConfiguration(configParams); assertThat(configuration.getParallelism()).isEqualTo(42); assertThat(configuration.getMaxPoolSize()).isEqualTo(42); assertThat(configuration.getSaturatePredicate().test(null)).isFalse(); } @Test void dynamicStrategyCreatesValidConfiguration() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("2.0")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; var configuration = strategy.createConfiguration(configParams); var availableProcessors = Runtime.getRuntime().availableProcessors(); assertThat(configuration.getParallelism()).isEqualTo(availableProcessors * 2); assertThat(configuration.getCorePoolSize()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMinimumRunnable()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + (availableProcessors * 2)); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); assertThat(configuration.getSaturatePredicate().test(null)).isTrue(); } @Test void dynamicSaturateStrategyCreatesValidConfiguration() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("2.0")); when(configParams.get("dynamic.max-pool-size-factor")).thenReturn(Optional.of("3.0")); when(configParams.get("dynamic.saturate")).thenReturn(Optional.of("false")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; var configuration = strategy.createConfiguration(configParams); var availableProcessors = Runtime.getRuntime().availableProcessors(); assertThat(configuration.getParallelism()).isEqualTo(availableProcessors * 2); assertThat(configuration.getCorePoolSize()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMinimumRunnable()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMaxPoolSize()).isEqualTo(availableProcessors * 6); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); assertThat(configuration.getSaturatePredicate().test(null)).isFalse(); } @Test void customStrategyCreatesValidConfiguration() { when(configParams.get("custom.class")).thenReturn( Optional.of(CustomParallelExecutionConfigurationStrategy.class.getName())); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.CUSTOM; var configuration = strategy.createConfiguration(configParams); assertThat(configuration.getParallelism()).isEqualTo(1); assertThat(configuration.getCorePoolSize()).isEqualTo(4); assertThat(configuration.getMinimumRunnable()).isEqualTo(2); assertThat(configuration.getMaxPoolSize()).isEqualTo(3); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(5); assertThat(configuration.getSaturatePredicate()).isNotNull(); assertThat(configuration.getSaturatePredicate().test(null)).isTrue(); } @ParameterizedTest @EnumSource void createsStrategyFromConfigParam(DefaultParallelExecutionConfigurationStrategy strategy) { when(configParams.get("strategy")).thenReturn(Optional.of(strategy.name().toLowerCase())); assertThat(DefaultParallelExecutionConfigurationStrategy.getStrategy(configParams)).isSameAs(strategy); } @Test void fixedStrategyThrowsExceptionWhenPropertyIsNotPresent() { when(configParams.get("fixed.parallelism")).thenReturn(Optional.empty()); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.FIXED; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void fixedStrategyThrowsExceptionWhenPropertyIsNotAnInteger() { when(configParams.get("fixed.parallelism")).thenReturn(Optional.of("foo")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.FIXED; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void dynamicStrategyUsesDefaultWhenPropertyIsNotPresent() { when(configParams.get("dynamic.factor")).thenReturn(Optional.empty()); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; var configuration = strategy.createConfiguration(configParams); var availableProcessors = Runtime.getRuntime().availableProcessors(); assertThat(configuration.getParallelism()).isEqualTo(availableProcessors); assertThat(configuration.getCorePoolSize()).isEqualTo(availableProcessors); assertThat(configuration.getMinimumRunnable()).isEqualTo(availableProcessors); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + availableProcessors); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); } @Test void dynamicStrategyThrowsExceptionWhenPropertyIsNotAnInteger() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("foo")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void dynamicStrategyThrowsExceptionWhenFactorIsZero() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("0")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void dynamicStrategyThrowsExceptionWhenFactorIsNegative() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("-1")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void dynamicStrategyUsesAtLeastParallelismOfOneWhenPropertyIsTooSmall() { when(configParams.get("dynamic.factor")).thenReturn(Optional.of("0.00000000001")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.DYNAMIC; var configuration = strategy.createConfiguration(configParams); assertThat(configuration.getParallelism()).isEqualTo(1); assertThat(configuration.getCorePoolSize()).isEqualTo(1); assertThat(configuration.getMinimumRunnable()).isEqualTo(1); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + 1); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); } @Test void customStrategyThrowsExceptionWhenPropertyIsNotPresent() { when(configParams.get("custom.class")).thenReturn(Optional.empty()); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.CUSTOM; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } @Test void customStrategyThrowsExceptionWhenClassDoesNotExist() { when(configParams.get("custom.class")).thenReturn(Optional.of("com.acme.ClassDoesNotExist")); ParallelExecutionConfigurationStrategy strategy = DefaultParallelExecutionConfigurationStrategy.CUSTOM; assertThrows(JUnitException.class, () -> strategy.createConfiguration(configParams)); } static class CustomParallelExecutionConfigurationStrategy implements ParallelExecutionConfigurationStrategy { @Override public ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { return new DefaultParallelExecutionConfiguration(1, 2, 3, 4, 5, __ -> true); } } } ForkJoinPoolHierarchicalTestExecutorServiceTests.java000066400000000000000000000031521455764576500444270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.platform.commons.JUnitException; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) class ForkJoinPoolHierarchicalTestExecutorServiceTests { @Mock ParallelExecutionConfiguration configuration; @Test void exceptionsFromInvalidConfigurationAreNotSwallowed() { when(configuration.getParallelism()).thenReturn(2); when(configuration.getMaxPoolSize()).thenReturn(1); // invalid, should be > parallelism when(configuration.getCorePoolSize()).thenReturn(1); when(configuration.getMinimumRunnable()).thenReturn(1); when(configuration.getSaturatePredicate()).thenReturn(__ -> true); when(configuration.getKeepAliveSeconds()).thenReturn(0); JUnitException exception = assertThrows(JUnitException.class, () -> new ForkJoinPoolHierarchicalTestExecutorService(configuration)); assertThat(exception).hasMessage("Failed to create ForkJoinPool"); assertThat(exception).rootCause().isInstanceOf(IllegalArgumentException.class); } } HierarchicalTestExecutorTests.java000066400000000000000000000721571455764576500406250ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode; import org.junit.platform.engine.support.hierarchical.Node.DynamicTestExecutor; import org.junit.platform.launcher.core.ConfigurationParametersFactoryForTests; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.stubbing.Answer; import org.opentest4j.TestAbortedException; /** * Micro-tests that verify behavior of {@link HierarchicalTestExecutor}. * * @since 1.0 */ @ExtendWith(MockitoExtension.class) class HierarchicalTestExecutorTests { @Spy MyContainer root = new MyContainer(UniqueId.root("container", "root")); @Mock EngineExecutionListener listener; MyEngineExecutionContext rootContext = new MyEngineExecutionContext(); HierarchicalTestExecutor executor; @BeforeEach void init() { executor = createExecutor(new SameThreadHierarchicalTestExecutorService()); } private HierarchicalTestExecutor createExecutor( HierarchicalTestExecutorService executorService) { var request = new ExecutionRequest(root, listener, null); return new HierarchicalTestExecutor<>(request, rootContext, executorService, OpenTest4JAwareThrowableCollector::new); } @Test void emptyRootDescriptor() throws Exception { var inOrder = inOrder(listener, root); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(root).after(rootContext); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(SUCCESSFUL); } @Test void rootDescriptorWithOneChildContainer() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).before(rootContext); inOrder.verify(child).after(rootContext); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(SUCCESSFUL); } @Test void rootDescriptorWithOneChildLeaf() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "child leaf"))); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); var aTestExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(child), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(aTestExecutionResult.getValue().getStatus()).isEqualTo(SUCCESSFUL); } @Test void skippingAContainer() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); when(child.shouldBeSkipped(rootContext)).thenReturn(Node.SkipResult.skip("in test")); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(child).cleanUp(rootContext); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); verify(listener, never()).executionStarted(child); verify(child, never()).execute(any(), any()); verify(listener, never()).executionFinished(eq(child), any(TestExecutionResult.class)); } @Test void skippingALeaf() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "child leaf"))); when(child.shouldBeSkipped(rootContext)).thenReturn(Node.SkipResult.skip("in test")); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(child).cleanUp(rootContext); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); verify(listener, never()).executionStarted(child); verify(child, never()).execute(any(), any()); verify(listener, never()).executionFinished(eq(child), any(TestExecutionResult.class)); } @Test void exceptionInShouldBeSkipped() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); var anException = new RuntimeException("in skip"); when(child.shouldBeSkipped(rootContext)).thenThrow(anException); root.addChild(child); var inOrder = inOrder(listener, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(child).cleanUp(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); verify(child, never()).execute(any(), any()); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(childExecutionResult.getValue().getThrowable()).containsSame(anException); } @Test void exceptionInContainerBeforeAll() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); root.addChild(child); var anException = new RuntimeException("in test"); when(root.before(rootContext)).thenThrow(anException); var inOrder = inOrder(listener, root, child); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(root).after(rootContext); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(anException); verify(child, never()).execute(any(), any()); } @Test void exceptionInContainerAfterAllAndCleanUp() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "child container"))); root.addChild(child); var afterException = new RuntimeException("in after()"); doThrow(afterException).when(root).after(rootContext); var cleanUpException = new RuntimeException("in cleanUp()"); doThrow(cleanUpException).when(root).cleanUp(rootContext); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); var inOrder = inOrder(listener, root, child); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(child), any(TestExecutionResult.class)); inOrder.verify(root).after(rootContext); inOrder.verify(root).cleanUp(rootContext); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); inOrder.verifyNoMoreInteractions(); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(afterException); assertThat(afterException.getSuppressed()).containsExactly(cleanUpException); } @Test void exceptionInPrepare() throws Exception { var prepareException = new RuntimeException("in prepare()"); doThrow(prepareException).when(root).prepare(rootContext); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); var inOrder = inOrder(listener, root); inOrder.verify(root).prepare(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); inOrder.verifyNoMoreInteractions(); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(prepareException); assertThat(prepareException.getSuppressed()).isEmpty(); } @Test void exceptionInCleanUp() throws Exception { var cleanUpException = new RuntimeException("in cleanUp()"); doThrow(cleanUpException).when(root).cleanUp(rootContext); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); var inOrder = inOrder(listener, root); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).execute(eq(rootContext), any()); inOrder.verify(root).after(rootContext); inOrder.verify(root).cleanUp(rootContext); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); inOrder.verifyNoMoreInteractions(); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(cleanUpException); assertThat(cleanUpException.getSuppressed()).isEmpty(); } @Test void exceptionInShouldBeSkippedAndCleanUp() throws Exception { var shouldBeSkippedException = new RuntimeException("in prepare()"); doThrow(shouldBeSkippedException).when(root).shouldBeSkipped(rootContext); var cleanUpException = new RuntimeException("in cleanUp()"); doThrow(cleanUpException).when(root).cleanUp(rootContext); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); var inOrder = inOrder(listener, root); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(root).cleanUp(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); inOrder.verifyNoMoreInteractions(); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(shouldBeSkippedException); assertThat(shouldBeSkippedException.getSuppressed()).containsExactly(cleanUpException); } @Test void exceptionInLeafExecute() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "leaf"))); var anException = new RuntimeException("in test"); when(child.execute(eq(rootContext), any())).thenThrow(anException); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); inOrder.verify(root).after(rootContext); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(childExecutionResult.getValue().getThrowable()).containsSame(anException); } @Test void abortInRootBeforeAll() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); root.addChild(child); var anAbortedException = new TestAbortedException("in BeforeAll"); when(root.before(rootContext)).thenThrow(anAbortedException); var inOrder = inOrder(listener, root, child); executor.execute(); var rootExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(root).after(rootContext); inOrder.verify(listener).executionFinished(eq(root), rootExecutionResult.capture()); assertThat(rootExecutionResult.getValue().getStatus()).isEqualTo(ABORTED); assertThat(rootExecutionResult.getValue().getThrowable()).containsSame(anAbortedException); verify(child, never()).execute(any(), any()); } @Test void abortInChildContainerBeforeAll() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); root.addChild(child); var anAbortedException = new TestAbortedException("in BeforeAll"); when(child.before(rootContext)).thenThrow(anAbortedException); var inOrder = inOrder(listener, root, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(root).prepare(rootContext); inOrder.verify(root).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(child).before(rootContext); inOrder.verify(child).after(rootContext); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); inOrder.verify(root).after(rootContext); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(ABORTED); assertThat(childExecutionResult.getValue().getThrowable()).containsSame(anAbortedException); verify(child, never()).execute(any(), any()); } @Test void abortInLeafExecute() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "leaf"))); var anAbortedException = new TestAbortedException("in test"); when(child.execute(eq(rootContext), any())).thenThrow(anAbortedException); root.addChild(child); var inOrder = inOrder(listener, root, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(root).before(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); inOrder.verify(root).after(rootContext); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(ABORTED); assertThat(childExecutionResult.getValue().getThrowable()).containsSame(anAbortedException); } @Test void executesDynamicTestDescriptors() throws Exception { var leafUniqueId = UniqueId.root("leaf", "child leaf"); var child = spy(new MyLeaf(leafUniqueId)); var dynamicTestDescriptor = spy(new MyLeaf(leafUniqueId.append("dynamic", "child"))); when(child.execute(any(), any())).thenAnswer(execute(dynamicTestDescriptor)); root.addChild(child); var inOrder = inOrder(listener, root, child, dynamicTestDescriptor); executor.execute(); var aTestExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).dynamicTestRegistered(dynamicTestDescriptor); inOrder.verify(dynamicTestDescriptor).prepare(rootContext); inOrder.verify(dynamicTestDescriptor).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(dynamicTestDescriptor); inOrder.verify(dynamicTestDescriptor).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(dynamicTestDescriptor), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(child), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(aTestExecutionResult.getAllValues()).extracting(TestExecutionResult::getStatus).containsExactly( SUCCESSFUL, SUCCESSFUL); } @Test void executesDynamicTestDescriptorsUsingContainerAndTestType() throws Exception { var child = spy(new MyContainerAndTestTestCase(root.getUniqueId().append("c&t", "child"))); var dynamicContainerAndTest = spy( new MyContainerAndTestTestCase(child.getUniqueId().append("c&t", "dynamicContainerAndTest"))); var dynamicLeaf = spy(new MyLeaf(dynamicContainerAndTest.getUniqueId().append("test", "dynamicLeaf"))); root.addChild(child); when(child.execute(any(), any())).thenAnswer(execute(dynamicContainerAndTest)); when(dynamicContainerAndTest.execute(any(), any())).thenAnswer(execute(dynamicLeaf)); when(dynamicLeaf.execute(any(), any())).thenAnswer(invocation -> { throw new AssertionError("test fails"); }); var inOrder = inOrder(listener, root, child, dynamicContainerAndTest, dynamicLeaf); executor.execute(); var aTestExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(listener).executionStarted(root); inOrder.verify(child).prepare(rootContext); inOrder.verify(child).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(child); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(listener).dynamicTestRegistered(dynamicContainerAndTest); inOrder.verify(dynamicContainerAndTest).prepare(rootContext); inOrder.verify(dynamicContainerAndTest).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(dynamicContainerAndTest); inOrder.verify(dynamicContainerAndTest).execute(eq(rootContext), any()); inOrder.verify(listener).dynamicTestRegistered(dynamicLeaf); inOrder.verify(dynamicLeaf).prepare(rootContext); inOrder.verify(dynamicLeaf).shouldBeSkipped(rootContext); inOrder.verify(listener).executionStarted(dynamicLeaf); inOrder.verify(dynamicLeaf).execute(eq(rootContext), any()); inOrder.verify(listener).executionFinished(eq(dynamicLeaf), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(dynamicContainerAndTest), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(child), aTestExecutionResult.capture()); inOrder.verify(listener).executionFinished(eq(root), any(TestExecutionResult.class)); assertThat(aTestExecutionResult.getAllValues()).extracting(TestExecutionResult::getStatus).containsExactly( FAILED, SUCCESSFUL, SUCCESSFUL); } @Test void executesDynamicTestDescriptorsWithCustomListener() { var leafUniqueId = UniqueId.root("leaf", "child leaf"); var child = spy(new MyLeaf(leafUniqueId)); var dynamicTestDescriptor = spy(new MyLeaf(leafUniqueId.append("dynamic", "child"))); root.addChild(child); var anotherListener = mock(EngineExecutionListener.class); when(child.execute(any(), any())).thenAnswer( useDynamicTestExecutor(executor -> executor.execute(dynamicTestDescriptor, anotherListener))); executor.execute(); var inOrder = inOrder(listener, anotherListener, root, child, dynamicTestDescriptor); inOrder.verify(anotherListener).dynamicTestRegistered(dynamicTestDescriptor); inOrder.verify(anotherListener).executionStarted(dynamicTestDescriptor); inOrder.verify(dynamicTestDescriptor).execute(eq(rootContext), any()); inOrder.verify(dynamicTestDescriptor).nodeFinished(rootContext, dynamicTestDescriptor, successful()); inOrder.verify(anotherListener).executionFinished(dynamicTestDescriptor, successful()); } @Test void canAbortExecutionOfDynamicChild() throws Exception { var leafUniqueId = UniqueId.root("leaf", "child leaf"); var child = spy(new MyLeaf(leafUniqueId)); var dynamicTestDescriptor = spy(new MyLeaf(leafUniqueId.append("dynamic", "child"))); root.addChild(child); var startedLatch = new CountDownLatch(1); var interrupted = new CompletableFuture(); when(child.execute(any(), any())).thenAnswer(useDynamicTestExecutor(executor -> { var future = executor.execute(dynamicTestDescriptor, EngineExecutionListener.NOOP); startedLatch.await(); future.cancel(true); executor.awaitFinished(); })); when(dynamicTestDescriptor.execute(any(), any())).thenAnswer(invocation -> { startedLatch.countDown(); try { new CountDownLatch(1).await(); // block until interrupted interrupted.complete(false); return null; } catch (InterruptedException e) { interrupted.complete(true); throw e; } }); var parameters = ConfigurationParametersFactoryForTests.create(Map.of(// DefaultParallelExecutionConfigurationStrategy.CONFIG_STRATEGY_PROPERTY_NAME, "fixed", // DefaultParallelExecutionConfigurationStrategy.CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, "2")); try (var executorService = new ForkJoinPoolHierarchicalTestExecutorService(parameters)) { createExecutor(executorService).execute().get(); } verify(listener).executionFinished(child, successful()); assertTrue(interrupted.get(), "dynamic node was interrupted"); } private Answer execute(TestDescriptor dynamicChild) { return useDynamicTestExecutor(executor -> executor.execute(dynamicChild)); } private Answer useDynamicTestExecutor(ThrowingConsumer action) { return invocation -> { DynamicTestExecutor dynamicTestExecutor = invocation.getArgument(1); action.accept(dynamicTestExecutor); return invocation.getArgument(0); }; } /** * Verifies support for unrecoverable exceptions. */ @Test void outOfMemoryErrorInShouldBeSkipped() throws Exception { var child = spy(new MyContainer(UniqueId.root("container", "child container"))); var outOfMemoryError = new OutOfMemoryError("in skip"); when(child.shouldBeSkipped(rootContext)).thenThrow(outOfMemoryError); root.addChild(child); Throwable actualException = assertThrows(OutOfMemoryError.class, () -> executor.execute()); assertSame(outOfMemoryError, actualException); } /** * Verifies support for unrecoverable exceptions. */ @Test void outOfMemoryErrorInLeafExecution() { var child = spy(new MyLeaf(UniqueId.root("leaf", "leaf"))); var outOfMemoryError = new OutOfMemoryError("in test"); when(child.execute(eq(rootContext), any())).thenThrow(outOfMemoryError); root.addChild(child); Throwable actualException = assertThrows(OutOfMemoryError.class, () -> executor.execute()); assertSame(outOfMemoryError, actualException); } @Test void exceptionInAfterDoesNotHideEarlierException() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "leaf"))); Exception exceptionInExecute = new RuntimeException("execute"); Exception exceptionInAfter = new RuntimeException("after"); doThrow(exceptionInExecute).when(child).execute(eq(rootContext), any()); doThrow(exceptionInAfter).when(child).after(eq(rootContext)); root.addChild(child); var inOrder = inOrder(listener, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(child).after(eq(rootContext)); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(childExecutionResult.getValue().getThrowable().get()).isSameAs( exceptionInExecute).hasSuppressedException(exceptionInAfter); } @Test void dynamicTestDescriptorsMustNotDeclareExclusiveResources() { var leafUniqueId = UniqueId.root("leaf", "child leaf"); var child = spy(new MyLeaf(leafUniqueId)); var dynamicTestDescriptor = spy(new MyLeaf(leafUniqueId.append("dynamic", "child"))); when(dynamicTestDescriptor.getExclusiveResources()).thenReturn( Set.of(new ExclusiveResource("foo", LockMode.READ))); when(child.execute(any(), any())).thenAnswer(execute(dynamicTestDescriptor)); root.addChild(child); executor.execute(); var aTestExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(dynamicTestDescriptor); verify(listener).executionFinished(eq(dynamicTestDescriptor), aTestExecutionResult.capture()); var executionResult = aTestExecutionResult.getValue(); assertThat(executionResult.getStatus()).isEqualTo(FAILED); assertThat(executionResult.getThrowable()).isPresent(); assertThat(executionResult.getThrowable().get()).hasMessageContaining( "Dynamic test descriptors must not declare exclusive resources"); } @Test void exceptionInAfterIsReportedInsteadOfEarlierTestAbortedException() throws Exception { var child = spy(new MyLeaf(UniqueId.root("leaf", "leaf"))); Exception exceptionInExecute = new TestAbortedException("execute"); Exception exceptionInAfter = new RuntimeException("after"); doThrow(exceptionInExecute).when(child).execute(eq(rootContext), any()); doThrow(exceptionInAfter).when(child).after(eq(rootContext)); root.addChild(child); var inOrder = inOrder(listener, child); executor.execute(); var childExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); inOrder.verify(child).execute(eq(rootContext), any()); inOrder.verify(child).after(eq(rootContext)); inOrder.verify(listener).executionFinished(eq(child), childExecutionResult.capture()); assertThat(childExecutionResult.getValue().getStatus()).isEqualTo(FAILED); assertThat(childExecutionResult.getValue().getThrowable().get()).isSameAs( exceptionInAfter).hasSuppressedException(exceptionInExecute); } // ------------------------------------------------------------------- private static class MyEngineExecutionContext implements EngineExecutionContext { } private static class MyContainer extends AbstractTestDescriptor implements Node { MyContainer(UniqueId uniqueId) { super(uniqueId, uniqueId.toString()); } @Override public Type getType() { return Type.CONTAINER; } } private static class MyLeaf extends AbstractTestDescriptor implements Node { MyLeaf(UniqueId uniqueId) { super(uniqueId, uniqueId.toString()); } @Override public MyEngineExecutionContext execute(MyEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { return context; } @Override public Type getType() { return Type.TEST; } } private static class MyContainerAndTestTestCase extends AbstractTestDescriptor implements Node { MyContainerAndTestTestCase(UniqueId uniqueId) { super(uniqueId, uniqueId.toString()); } @Override public Type getType() { return Type.CONTAINER_AND_TEST; } } } LockManagerTests.java000066400000000000000000000102631455764576500360410ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_KEY; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ_WRITE; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode; /** * @since 1.3 */ class LockManagerTests { private LockManager lockManager = new LockManager(); @Test void returnsNopLockWithoutExclusiveResources() { Collection resources = Set.of(); var locks = getLocks(resources, NopLock.class); assertThat(locks).isEmpty(); } @Test void returnsSingleLockForSingleExclusiveResource() { Collection resources = Set.of(new ExclusiveResource("foo", READ)); var locks = getLocks(resources, SingleLock.class); assertThat(locks).hasSize(1); assertThat(locks.get(0)).isInstanceOf(ReadLock.class); } @Test void returnsCompositeLockForMultipleDifferentExclusiveResources() { Collection resources = List.of( // new ExclusiveResource("a", READ), // new ExclusiveResource("b", READ_WRITE)); var locks = getLocks(resources, CompositeLock.class); assertThat(locks).hasSize(2); assertThat(locks.get(0)).isInstanceOf(ReadLock.class); assertThat(locks.get(1)).isInstanceOf(WriteLock.class); } @Test void reusesSameLockForExclusiveResourceWithSameKey() { Collection resources = Set.of(new ExclusiveResource("foo", READ)); var locks1 = getLocks(resources, SingleLock.class); var locks2 = getLocks(resources, SingleLock.class); assertThat(locks1).hasSize(1); assertThat(locks2).hasSize(1); assertThat(locks1.get(0)).isSameAs(locks2.get(0)); } @Test void returnsWriteLockForExclusiveResourceWithBothLockModes() { Collection resources = List.of( // new ExclusiveResource("bar", READ), // new ExclusiveResource("foo", READ), // new ExclusiveResource("foo", READ_WRITE), // new ExclusiveResource("bar", READ_WRITE)); var locks = getLocks(resources, CompositeLock.class); assertThat(locks).hasSize(2); assertThat(locks.get(0)).isInstanceOf(WriteLock.class); assertThat(locks.get(1)).isInstanceOf(WriteLock.class); } @ParameterizedTest @EnumSource void globalLockComesFirst(LockMode globalLockMode) { Collection resources = List.of( // new ExclusiveResource("___foo", READ), // new ExclusiveResource("foo", READ_WRITE), // new ExclusiveResource(GLOBAL_KEY, globalLockMode), // new ExclusiveResource("bar", READ_WRITE)); var locks = getLocks(resources, CompositeLock.class); assertThat(locks).hasSize(4); assertThat(locks.get(0)).isEqualTo(getSingleLock(GLOBAL_KEY, globalLockMode)); assertThat(locks.get(1)).isEqualTo(getSingleLock("___foo", READ)); assertThat(locks.get(2)).isEqualTo(getSingleLock("bar", READ_WRITE)); assertThat(locks.get(3)).isEqualTo(getSingleLock("foo", READ_WRITE)); } private Lock getSingleLock(String globalResourceLockKey, LockMode read) { return getLocks(Set.of(new ExclusiveResource(globalResourceLockKey, read)), SingleLock.class).get(0); } private List getLocks(Collection resources, Class type) { var lock = lockManager.getLockForResources(resources); assertThat(lock).isInstanceOf(type); return ResourceLockSupport.getLocks(lock); } } MemoryLeakTests.java000066400000000000000000000031471455764576500357260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; /** * Integration tests intended to verify that memory leaks do not * exist with regard to the "context" held by {@link NodeTestTask}. * * @since 5.3.1 * @see GitHub issue #1578 */ // Explicitly specifying Lifecycle.PER_METHOD to be certain that the // test instance state is recreated for every test method executed. @TestInstance(Lifecycle.PER_METHOD) class MemoryLeakTests { // Allocate 500 MB of memory per test method. // // If the test instance is garbage collected, this should not cause any // problems for the JUnit 5 build; however, if the instances of this test // class are NOT garbage collected, we should run out of memory pretty // quickly since the instances of this test class would consume 5GB of // heap space. final byte[] state = new byte[524_288_000]; @Test void test01() { } @Test void test02() { } @Test void test03() { } @Test void test04() { } @Test void test05() { } @Test void test06() { } @Test void test07() { } @Test void test08() { } @Test void test09() { } @Test void test10() { } } NodeTreeWalkerIntegrationTests.java000066400000000000000000000241651455764576500407430ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ_WRITE; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ_WRITE; import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.SAME_THREAD; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.function.Function; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceAccessMode; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; /** * @since 1.3 */ class NodeTreeWalkerIntegrationTests { LockManager lockManager = new LockManager(); NodeTreeWalker nodeTreeWalker = new NodeTreeWalker(lockManager); @Test void pullUpExclusiveChildResourcesToTestClass() { var engineDescriptor = discover(TestCaseWithResourceLock.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ), getReadWriteLock("a"), getReadWriteLock("b"))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).contains(SAME_THREAD); } @Test void setsForceExecutionModeForChildrenWithWriteLocksOnClass() { var engineDescriptor = discover(TestCaseWithResourceWriteLockOnClass.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ), getReadWriteLock("a"))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).contains(SAME_THREAD); } @Test void doesntSetForceExecutionModeForChildrenWithReadLocksOnClass() { var engineDescriptor = discover(TestCaseWithResourceReadLockOnClass.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ), getReadLock("a"))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).isEmpty(); } @Test void setsForceExecutionModeForChildrenWithReadLocksOnClassAndWriteLockOnTest() { var engineDescriptor = discover(TestCaseWithResourceReadLockOnClassAndWriteClockOnTestCase.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ), getReadWriteLock("a"))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).contains(SAME_THREAD); } @Test void doesntSetForceExecutionModeForChildrenWithReadLocksOnClassAndReadLockOnTest() { var engineDescriptor = discover(TestCaseWithResourceReadLockOnClassAndReadClockOnTestCase.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ), getReadLock("a"), getReadLock("b"))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var testMethodDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).isEmpty(); } @Test void leavesResourceLockOnTestMethodWhenClassDoesNotUseResource() { var engineDescriptor = discover(TestCaseWithoutResourceLock.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); assertThat(testClassDescriptor.getChildren()).hasSize(2); var children = testClassDescriptor.getChildren().iterator(); var testMethodDescriptor = children.next(); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getReadWriteLock("a"))); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).isEmpty(); var nestedTestClassDescriptor = children.next(); assertThat(advisor.getResourceLock(nestedTestClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getReadWriteLock("b"), getReadWriteLock("c"))); assertThat(advisor.getForcedExecutionMode(nestedTestClassDescriptor)).isEmpty(); var nestedTestMethodDescriptor = getOnlyElement(nestedTestClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(nestedTestMethodDescriptor)).extracting(allLocks()).isEqualTo(List.of()); assertThat(advisor.getForcedExecutionMode(nestedTestMethodDescriptor)).contains(SAME_THREAD); } @Test void coarsensGlobalLockToEngineDescriptorChild() { var engineDescriptor = discover(TestCaseWithGlobalLockRequiringChild.class); var advisor = nodeTreeWalker.walk(engineDescriptor); var testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); assertThat(advisor.getResourceLock(testClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ_WRITE))); assertThat(advisor.getForcedExecutionMode(testClassDescriptor)).isEmpty(); var nestedTestClassDescriptor = getOnlyElement(testClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(nestedTestClassDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ))); assertThat(advisor.getForcedExecutionMode(nestedTestClassDescriptor)).contains(SAME_THREAD); var testMethodDescriptor = getOnlyElement(nestedTestClassDescriptor.getChildren()); assertThat(advisor.getResourceLock(testMethodDescriptor)).extracting(allLocks()) // .isEqualTo(List.of(getLock(GLOBAL_READ_WRITE))); assertThat(advisor.getForcedExecutionMode(testMethodDescriptor)).contains(SAME_THREAD); } private static Function> allLocks() { return ResourceLockSupport::getLocks; } private Lock getReadWriteLock(String key) { return getLock(new ExclusiveResource(key, READ_WRITE)); } private Lock getReadLock(String key) { return getLock(new ExclusiveResource(key, READ)); } private Lock getLock(ExclusiveResource exclusiveResource) { return getOnlyElement(ResourceLockSupport.getLocks(lockManager.getLockForResource(exclusiveResource))); } private TestDescriptor discover(Class testClass) { var discoveryRequest = request().selectors(selectClass(testClass)).build(); return new JupiterTestEngine().discover(discoveryRequest, UniqueId.forEngine("junit-jupiter")); } @ResourceLock("a") static class TestCaseWithResourceLock { @Test @ResourceLock("b") void test() { } } static class TestCaseWithoutResourceLock { @Test @ResourceLock("a") void test() { } @Nested @ResourceLock("c") class NestedTestCaseWithResourceLock { @Test @ResourceLock("b") void test() { } } } static class TestCaseWithGlobalLockRequiringChild { @Nested class NestedTestCaseWithResourceLock { @Test @ResourceLock(ExclusiveResource.GLOBAL_KEY) void test() { } } } @ResourceLock("a") static class TestCaseWithResourceWriteLockOnClass { @Test void test() { } } @ResourceLock(value = "a", mode = ResourceAccessMode.READ) static class TestCaseWithResourceReadLockOnClass { @Test void test() { } } @ResourceLock(value = "a", mode = ResourceAccessMode.READ) static class TestCaseWithResourceReadLockOnClassAndWriteClockOnTestCase { @Test @ResourceLock("a") void test() { } } @ResourceLock(value = "a", mode = ResourceAccessMode.READ) static class TestCaseWithResourceReadLockOnClassAndReadClockOnTestCase { @Test @ResourceLock(value = "b", mode = ResourceAccessMode.READ) void test() { } } } ParallelExecutionIntegrationTests.java000066400000000000000000000612321455764576500415040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT; import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD; import static org.junit.jupiter.engine.Constants.DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_PARALLEL_EXECUTION_MODE; import static org.junit.jupiter.engine.Constants.PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.EventConditions.type; import static org.junit.platform.testkit.engine.EventType.REPORTING_ENTRY_PUBLISHED; import java.net.URL; import java.net.URLClassLoader; import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.IntStream; import java.util.stream.Stream; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.MethodOrderer.MethodName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Event; /** * @since 1.3 */ class ParallelExecutionIntegrationTests { @Test void successfulParallelTest(TestReporter reporter) { var events = executeConcurrently(3, SuccessfulParallelTestCase.class); var startedTimestamps = getTimestampsFor(events, event(test(), started())); var finishedTimestamps = getTimestampsFor(events, event(test(), finishedSuccessfully())); reporter.publishEntry("startedTimestamps", startedTimestamps.toString()); reporter.publishEntry("finishedTimestamps", finishedTimestamps.toString()); assertThat(startedTimestamps).hasSize(3); assertThat(finishedTimestamps).hasSize(3); assertThat(startedTimestamps).allMatch(startTimestamp -> finishedTimestamps.stream().noneMatch( finishedTimestamp -> finishedTimestamp.isBefore(startTimestamp))); assertThat(ThreadReporter.getThreadNames(events)).hasSize(3); } @Test void failingTestWithoutLock() { var events = executeConcurrently(3, FailingWithoutLockTestCase.class); assertThat(events.stream().filter(event(test(), finishedWithFailure())::matches)).hasSize(2); } @Test void successfulTestWithMethodLock() { var events = executeConcurrently(3, SuccessfulWithMethodLockTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(3); assertThat(ThreadReporter.getThreadNames(events)).hasSize(3); } @Test void successfulTestWithClassLock() { var events = executeConcurrently(3, SuccessfulWithClassLockTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(3); assertThat(ThreadReporter.getThreadNames(events)).hasSize(1); } @Test void testCaseWithFactory() { var events = executeConcurrently(3, TestCaseWithTestFactory.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(3); assertThat(ThreadReporter.getThreadNames(events)).hasSize(1); } @Test void customContextClassLoader() { var currentThread = Thread.currentThread(); var currentLoader = currentThread.getContextClassLoader(); var smilingLoader = new URLClassLoader("(-:", new URL[0], ClassLoader.getSystemClassLoader()); currentThread.setContextClassLoader(smilingLoader); try { var events = executeConcurrently(3, SuccessfulWithMethodLockTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(3); assertThat(ThreadReporter.getThreadNames(events)).hasSize(3); assertThat(ThreadReporter.getLoaderNames(events)).containsExactly("(-:"); } finally { currentThread.setContextClassLoader(currentLoader); } } @RepeatedTest(10) void mixingClassAndMethodLevelLocks() { var events = executeConcurrently(4, TestCaseWithSortedLocks.class, TestCaseWithUnsortedLocks.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(6); assertThat(ThreadReporter.getThreadNames(events).count()).isLessThanOrEqualTo(2); } @RepeatedTest(10) void locksOnNestedTests() { var events = executeConcurrently(3, TestCaseWithNestedLocks.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(6); assertThat(ThreadReporter.getThreadNames(events)).hasSize(1); } @Test void afterHooksAreCalledAfterConcurrentDynamicTestsAreFinished() { var events = executeConcurrently(3, ConcurrentDynamicTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(1); var timestampedEvents = ConcurrentDynamicTestCase.events; assertThat(timestampedEvents.get("afterEach")).isAfterOrEqualTo(timestampedEvents.get("dynamicTestFinished")); } /** * @since 1.4 * @see gh-1688 */ @Test void threadInterruptedByUserCode() { var events = executeConcurrently(3, InterruptedThreadTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(4); } @Test void executesTestTemplatesWithResourceLocksInSameThread() { var events = executeConcurrently(2, ConcurrentTemplateTestCase.class); assertThat(events.stream().filter(event(test(), finishedSuccessfully())::matches)).hasSize(10); assertThat(ThreadReporter.getThreadNames(events)).hasSize(1); } @Test void executesClassesInParallelIfEnabledViaConfigurationParameter() { ParallelClassesTestCase.GLOBAL_BARRIER.reset(); var configParams = Map.of(DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME, "concurrent"); var results = executeWithFixedParallelism(3, configParams, ParallelClassesTestCaseA.class, ParallelClassesTestCaseB.class, ParallelClassesTestCaseC.class); results.testEvents().assertStatistics(stats -> stats.succeeded(9)); assertThat(ThreadReporter.getThreadNames(results.allEvents().list())).hasSize(3); var testClassA = findFirstTestDescriptor(results, container(ParallelClassesTestCaseA.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassA))).hasSize(1); var testClassB = findFirstTestDescriptor(results, container(ParallelClassesTestCaseB.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassB))).hasSize(1); var testClassC = findFirstTestDescriptor(results, container(ParallelClassesTestCaseC.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassC))).hasSize(1); } @Test void executesMethodsInParallelIfEnabledViaConfigurationParameter() { ParallelMethodsTestCase.barriersPerClass.clear(); var configParams = Map.of( // DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent", // DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME, "same_thread"); var results = executeWithFixedParallelism(3, configParams, ParallelMethodsTestCaseA.class, ParallelMethodsTestCaseB.class, ParallelMethodsTestCaseC.class); results.testEvents().assertStatistics(stats -> stats.succeeded(9)); assertThat(ThreadReporter.getThreadNames(results.allEvents().list())).hasSizeGreaterThanOrEqualTo(3); var testClassA = findFirstTestDescriptor(results, container(ParallelMethodsTestCaseA.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassA))).hasSize(3); var testClassB = findFirstTestDescriptor(results, container(ParallelMethodsTestCaseB.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassB))).hasSize(3); var testClassC = findFirstTestDescriptor(results, container(ParallelMethodsTestCaseC.class)); assertThat(ThreadReporter.getThreadNames(getEventsOfChildren(results, testClassC))).hasSize(3); } @Test void canRunTestsIsolatedFromEachOther() { var events = executeConcurrently(2, IsolatedTestCase.class); assertThat(events.stream().filter(event(test(), finishedWithFailure())::matches)).isEmpty(); } @Test void canRunTestsIsolatedFromEachOtherWithNestedCases() { var events = executeConcurrently(4, NestedIsolatedTestCase.class); assertThat(events.stream().filter(event(test(), finishedWithFailure())::matches)).isEmpty(); } @Test void canRunTestsIsolatedFromEachOtherAcrossClasses() { var events = executeConcurrently(4, IndependentClasses.A.class, IndependentClasses.B.class); assertThat(events.stream().filter(event(test(), finishedWithFailure())::matches)).isEmpty(); } @RepeatedTest(10) void canRunTestsIsolatedFromEachOtherAcrossClassesWithOtherResourceLocks() { var events = executeConcurrently(4, IndependentClasses.B.class, IndependentClasses.C.class); assertThat(events.stream().filter(event(test(), finishedWithFailure())::matches)).isEmpty(); } @Isolated("testing") static class IsolatedTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(2); } @Test void a() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } } static class NestedIsolatedTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(6); } @Test void a() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Nested class Inner { @Test void a() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Nested @Isolated class InnerInner { @Test void a() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } } } } static class IndependentClasses { static AtomicInteger sharedResource = new AtomicInteger(); static CountDownLatch countDownLatch = new CountDownLatch(4); static class A { @Test void a() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } } @Isolated static class B { @Test void a() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } } @ResourceLock("other") static class C { @Test void a() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } @Test void b() throws Exception { storeAndBlockAndCheck(sharedResource, countDownLatch); } } } private List getEventsOfChildren(EngineExecutionResults results, TestDescriptor container) { return results.testEvents().filter( event -> event.getTestDescriptor().getParent().orElseThrow().equals(container)).collect(toList()); } private TestDescriptor findFirstTestDescriptor(EngineExecutionResults results, Condition condition) { return results.allEvents().filter(condition::matches).map(Event::getTestDescriptor).findFirst().orElseThrow(); } private List getTimestampsFor(List events, Condition condition) { // @formatter:off return events.stream() .filter(condition::matches) .map(Event::getTimestamp) .collect(toList()); // @formatter:on } private List executeConcurrently(int parallelism, Class... testClasses) { return executeWithFixedParallelism(parallelism, Map.of(DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent"), testClasses).allEvents().list(); } private EngineExecutionResults executeWithFixedParallelism(int parallelism, Map configParams, Class... testClasses) { // @formatter:off var discoveryRequest = request() .selectors(Arrays.stream(testClasses).map(DiscoverySelectors::selectClass).collect(toList())) .configurationParameter(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, String.valueOf(true)) .configurationParameter(PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME, "fixed") .configurationParameter(PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, String.valueOf(parallelism)) .configurationParameters(configParams) .build(); // @formatter:on return EngineTestKit.execute("junit-jupiter", discoveryRequest); } // ------------------------------------------------------------------------- @ExtendWith(ThreadReporter.class) static class SuccessfulParallelTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(3); } @Test void firstTest() throws Exception { incrementAndBlock(sharedResource, countDownLatch); } @Test void secondTest() throws Exception { incrementAndBlock(sharedResource, countDownLatch); } @Test void thirdTest() throws Exception { incrementAndBlock(sharedResource, countDownLatch); } } @ExtendWith(ThreadReporter.class) static class FailingWithoutLockTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(3); } @Test void firstTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void secondTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void thirdTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } } @ExtendWith(ThreadReporter.class) static class SuccessfulWithMethodLockTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(3); } @Test @ResourceLock("sharedResource") void firstTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test @ResourceLock("sharedResource") void secondTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test @ResourceLock("sharedResource") void thirdTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } } @ExtendWith(ThreadReporter.class) @ResourceLock("sharedResource") static class SuccessfulWithClassLockTestCase { static AtomicInteger sharedResource; static CountDownLatch countDownLatch; @BeforeAll static void initialize() { sharedResource = new AtomicInteger(); countDownLatch = new CountDownLatch(3); } @Test void firstTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void secondTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } @Test void thirdTest() throws Exception { incrementBlockAndCheck(sharedResource, countDownLatch); } } static class TestCaseWithTestFactory { @TestFactory @Execution(SAME_THREAD) Stream testFactory(TestReporter testReporter) { var sharedResource = new AtomicInteger(0); var countDownLatch = new CountDownLatch(3); return IntStream.range(0, 3).mapToObj(i -> dynamicTest("test " + i, () -> { incrementBlockAndCheck(sharedResource, countDownLatch); testReporter.publishEntry("thread", Thread.currentThread().getName()); })); } } private static final ReentrantLock A = new ReentrantLock(); private static final ReentrantLock B = new ReentrantLock(); @ExtendWith(ThreadReporter.class) @ResourceLock("A") static class TestCaseWithSortedLocks { @ResourceLock("B") @Test void firstTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @Execution(CONCURRENT) @ResourceLock("B") @Test void secondTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @ResourceLock("B") @Test void thirdTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @AfterEach void unlock() { B.unlock(); A.unlock(); } } @ExtendWith(ThreadReporter.class) @ResourceLock("B") static class TestCaseWithUnsortedLocks { @ResourceLock("A") @Test void firstTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } @Execution(CONCURRENT) @ResourceLock("A") @Test void secondTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } @ResourceLock("A") @Test void thirdTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } @AfterEach void unlock() { A.unlock(); B.unlock(); } } @ExtendWith(ThreadReporter.class) @ResourceLock("A") static class TestCaseWithNestedLocks { @ResourceLock("B") @Test void firstTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @Execution(CONCURRENT) @ResourceLock("B") @Test void secondTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @Test void thirdTest() { assertTrue(A.tryLock()); assertTrue(B.tryLock()); } @AfterEach void unlock() { A.unlock(); B.unlock(); } @Nested @ResourceLock("B") class B { @ResourceLock("A") @Test void firstTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } @ResourceLock("A") @Test void secondTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } @Test void thirdTest() { assertTrue(B.tryLock()); assertTrue(A.tryLock()); } } } @Execution(CONCURRENT) static class ConcurrentDynamicTestCase { static Map events; @BeforeAll static void beforeAll() { events = new ConcurrentHashMap<>(); } @AfterEach void afterEach() { events.put("afterEach", Instant.now()); } @TestFactory DynamicTest testFactory() { return dynamicTest("slow", () -> { Thread.sleep(100); events.put("dynamicTestFinished", Instant.now()); }); } } @TestMethodOrder(MethodName.class) static class InterruptedThreadTestCase { @Test void test1() { Thread.currentThread().interrupt(); } @Test void test2() throws InterruptedException { Thread.sleep(10); } @Test void test3() { Thread.currentThread().interrupt(); } @Test void test4() throws InterruptedException { Thread.sleep(10); } } @Execution(CONCURRENT) @ExtendWith(ThreadReporter.class) static class ConcurrentTemplateTestCase { @RepeatedTest(10) @ResourceLock("a") void repeatedTest() throws Exception { Thread.sleep(100); } } @ExtendWith(ThreadReporter.class) static abstract class BarrierTestCase { @Test void test1() throws Exception { getBarrier().await(); } @Test void test2() throws Exception { getBarrier().await(); } @Test void test3() throws Exception { getBarrier().await(); } abstract CyclicBarrier getBarrier(); } static class ParallelMethodsTestCase extends BarrierTestCase { static final Map, CyclicBarrier> barriersPerClass = new ConcurrentHashMap<>(); @Override CyclicBarrier getBarrier() { return barriersPerClass.computeIfAbsent(this.getClass(), key -> new CyclicBarrier(3)); } } static class ParallelClassesTestCase extends BarrierTestCase { static final CyclicBarrier GLOBAL_BARRIER = new CyclicBarrier(3); @Override CyclicBarrier getBarrier() { return GLOBAL_BARRIER; } } static class ParallelClassesTestCaseA extends ParallelClassesTestCase { } static class ParallelClassesTestCaseB extends ParallelClassesTestCase { } static class ParallelClassesTestCaseC extends ParallelClassesTestCase { } static class ParallelMethodsTestCaseA extends ParallelMethodsTestCase { } static class ParallelMethodsTestCaseB extends ParallelMethodsTestCase { } static class ParallelMethodsTestCaseC extends ParallelMethodsTestCase { } private static void incrementBlockAndCheck(AtomicInteger sharedResource, CountDownLatch countDownLatch) throws InterruptedException { var value = incrementAndBlock(sharedResource, countDownLatch); assertEquals(value, sharedResource.get()); } private static int incrementAndBlock(AtomicInteger sharedResource, CountDownLatch countDownLatch) throws InterruptedException { var value = sharedResource.incrementAndGet(); countDownLatch.countDown(); countDownLatch.await(estimateSimulatedTestDurationInMiliseconds(), MILLISECONDS); return value; } private static void storeAndBlockAndCheck(AtomicInteger sharedResource, CountDownLatch countDownLatch) throws InterruptedException { var value = sharedResource.get(); countDownLatch.countDown(); countDownLatch.await(estimateSimulatedTestDurationInMiliseconds(), MILLISECONDS); assertEquals(value, sharedResource.get()); } /** * To simulate tests running in parallel tests will modify a shared * resource, simulate work by waiting, then check if the shared resource was * not modified by any other thread. * * Depending on system performance the simulation of work needs to be longer * on slower systems to ensure tests can run in parallel. * * Currently CI is known to be slow. */ private static long estimateSimulatedTestDurationInMiliseconds() { var runningInCi = Boolean.valueOf(System.getenv("CI")); return runningInCi ? 1000 : 100; } static class ThreadReporter implements AfterTestExecutionCallback { private static Stream getLoaderNames(List events) { return getValues(events, "loader"); } private static Stream getThreadNames(List events) { return getValues(events, "thread"); } private static Stream getValues(List events, String key) { // @formatter:off return events.stream() .filter(type(REPORTING_ENTRY_PUBLISHED)::matches) .map(event -> event.getPayload(ReportEntry.class).orElseThrow()) .map(ReportEntry::getKeyValuePairs) .filter(keyValuePairs -> keyValuePairs.containsKey(key)) .map(keyValuePairs -> keyValuePairs.get(key)) .distinct(); // @formatter:on } @Override public void afterTestExecution(ExtensionContext context) { context.publishReportEntry("thread", Thread.currentThread().getName()); context.publishReportEntry("loader", Thread.currentThread().getContextClassLoader().getName()); } } } ResourceLockSupport.java000066400000000000000000000013571455764576500366340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import java.util.List; import java.util.concurrent.locks.Lock; class ResourceLockSupport { static List getLocks(ResourceLock resourceLock) { if (resourceLock instanceof NopLock) { return List.of(); } if (resourceLock instanceof SingleLock) { return List.of(((SingleLock) resourceLock).getLock()); } return ((CompositeLock) resourceLock).getLocks(); } } SameThreadExecutionIntegrationTests.java000066400000000000000000000045231455764576500417650ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.MethodOrderer.MethodName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.testkit.engine.EngineTestKit; /** * @since 1.4 */ class SameThreadExecutionIntegrationTests { /** * @see gh-1688 */ @Test @TrackLogRecords void threadInterruptedByUserCode(LogRecordListener listener) { EngineTestKit.engine("junit-jupiter")// .selectors(selectClass(InterruptedThreadTestCase.class))// .execute()// .testEvents()// .assertStatistics(stats -> stats.succeeded(4)); assertThat(firstDebugLogRecord(listener).getMessage()).matches( "Execution of TestDescriptor with display name .+test1.+ and " + "unique ID .+ failed to clear the 'interrupted status' flag " + "for the current thread. JUnit has cleared the flag, but you " + "may wish to investigate why the flag was not cleared by user code."); } private LogRecord firstDebugLogRecord(LogRecordListener listener) throws AssertionError { return listener.stream(NodeTestTask.class, Level.FINE).findFirst().orElseThrow( () -> new AssertionError("Failed to find debug log record")); } // ------------------------------------------------------------------------- @TestMethodOrder(MethodName.class) static class InterruptedThreadTestCase { @Test void test1() { Thread.currentThread().interrupt(); } @Test void test2() throws InterruptedException { Thread.sleep(10); } @Test void test3() { Thread.currentThread().interrupt(); } @Test void test4() throws InterruptedException { Thread.sleep(10); } } } SingleLockTests.java000066400000000000000000000017401455764576500357100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.locks.ReentrantLock; import org.junit.jupiter.api.Test; /** * @since 1.3 */ class SingleLockTests { @Test @SuppressWarnings("resource") void acquire() throws Exception { var lock = new ReentrantLock(); new SingleLock(lock).acquire(); assertTrue(lock.isLocked()); } @Test @SuppressWarnings("resource") void release() throws Exception { var lock = new ReentrantLock(); new SingleLock(lock).acquire().close(); assertFalse(lock.isLocked()); } } SingleTestExecutorTests.java000066400000000000000000000033571455764576500374640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import java.util.Optional; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; /** * @since 1.0 */ @SuppressWarnings("deprecation") class SingleTestExecutorTests { @Test void executeSafelySuccessful() { var result = new SingleTestExecutor().executeSafely(() -> { }); assertEquals(SUCCESSFUL, result.getStatus()); assertEquals(Optional.empty(), result.getThrowable()); } @Test void executeSafelyAborted() { var testAbortedException = new TestAbortedException("assumption violated"); var result = new SingleTestExecutor().executeSafely(() -> { throw testAbortedException; }); assertEquals(ABORTED, result.getStatus()); assertSame(testAbortedException, result.getThrowable().get()); } @Test void executeSafelyFailed() { var assertionError = new AssertionError("assumption violated"); var result = new SingleTestExecutor().executeSafely(() -> { throw assertionError; }); assertEquals(FAILED, result.getStatus()); assertSame(assertionError, result.getThrowable().get()); } } ThrowableCollectorTests.java000066400000000000000000000036741455764576500374640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.hierarchical; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import java.util.Optional; import org.junit.jupiter.api.Test; /** * @since 1.6 */ class ThrowableCollectorTests { @Test void successfulExecution() { var collector = new ThrowableCollector(x -> true); collector.execute(() -> { }); var result = collector.toTestExecutionResult(); assertEquals(SUCCESSFUL, result.getStatus()); assertEquals(Optional.empty(), result.getThrowable()); } @Test void abortedExecution() { var customAbort = new CustomAbort(); var collector = new ThrowableCollector(CustomAbort.class::isInstance); collector.execute(() -> { throw customAbort; }); var result = collector.toTestExecutionResult(); assertEquals(ABORTED, result.getStatus()); assertSame(customAbort, result.getThrowable().get()); } @Test void failedExecution() { var assertionError = new AssertionError("assertion violated"); var collector = new ThrowableCollector(CustomAbort.class::isInstance); collector.execute(() -> { throw assertionError; }); var result = collector.toTestExecutionResult(); assertEquals(FAILED, result.getStatus()); assertSame(assertionError, result.getThrowable().get()); } private static class CustomAbort extends Error { private static final long serialVersionUID = 1L; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/store/000077500000000000000000000000001455764576500305635ustar00rootroot00000000000000NamespacedHierarchicalStoreTests.java000066400000000000000000000321501455764576500377470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/engine/support/store/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.engine.support.store; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.commons.test.ConcurrencyTestingUtils.executeConcurrently; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; /** * Unit tests for {@link NamespacedHierarchicalStore}. * * @since 5.0 */ public class NamespacedHierarchicalStoreTests { private final Object key = "key"; private final Object value = "value"; private final String namespace = "ns"; private final NamespacedHierarchicalStore.CloseAction closeAction = mock(); private final NamespacedHierarchicalStore grandParentStore = new NamespacedHierarchicalStore<>(null, closeAction); private final NamespacedHierarchicalStore parentStore = grandParentStore.newChild(); private final NamespacedHierarchicalStore store = parentStore.newChild(); @Nested class StoringValuesTests { @Test void getWithUnknownKeyReturnsNull() { assertNull(store.get(namespace, "unknown key")); } @Test void putAndGetWithSameKey() { store.put(namespace, key, value); assertEquals(value, store.get(namespace, key)); } @Test void valueCanBeReplaced() { store.put(namespace, key, value); Object newValue = new Object(); assertEquals(value, store.put(namespace, key, newValue)); assertEquals(newValue, store.get(namespace, key)); } @Test void valueIsComputedIfAbsent() { assertNull(store.get(namespace, key)); assertEquals(value, store.getOrComputeIfAbsent(namespace, key, innerKey -> value)); assertEquals(value, store.get(namespace, key)); } @Test void valueIsNotComputedIfPresentLocally() { store.put(namespace, key, value); assertEquals(value, store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value")); assertEquals(value, store.get(namespace, key)); } @Test void valueIsNotComputedIfPresentInParent() { parentStore.put(namespace, key, value); assertEquals(value, store.getOrComputeIfAbsent(namespace, key, k -> "a different value")); assertEquals(value, store.get(namespace, key)); } @Test void valueIsNotComputedIfPresentInGrandParent() { grandParentStore.put(namespace, key, value); assertEquals(value, store.getOrComputeIfAbsent(namespace, key, k -> "a different value")); assertEquals(value, store.get(namespace, key)); } @Test void nullIsAValidValueToPut() { store.put(namespace, key, null); assertNull(store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value")); assertNull(store.get(namespace, key)); } @Test void keysCanBeRemoved() { store.put(namespace, key, value); assertEquals(value, store.remove(namespace, key)); assertNull(store.get(namespace, key)); assertEquals("a different value", store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value")); } @Test void sameKeyWithDifferentNamespaces() { Object value1 = createObject("value1"); String namespace1 = "ns1"; Object value2 = createObject("value2"); String namespace2 = "ns2"; store.put(namespace1, key, value1); store.put(namespace2, key, value2); assertEquals(value1, store.get(namespace1, key)); assertEquals(value2, store.get(namespace2, key)); } @Test void valueIsComputedIfAbsentInDifferentNamespace() { String namespace1 = "ns1"; String namespace2 = "ns2"; assertEquals(value, store.getOrComputeIfAbsent(namespace1, key, innerKey -> value)); assertEquals(value, store.get(namespace1, key)); assertNull(store.get(namespace2, key)); } @Test void keyIsOnlyRemovedInGivenNamespace() { String namespace1 = "ns1"; String namespace2 = "ns2"; Object value1 = createObject("value1"); Object value2 = createObject("value2"); store.put(namespace1, key, value1); store.put(namespace2, key, value2); store.remove(namespace1, key); assertNull(store.get(namespace1, key)); assertEquals(value2, store.get(namespace2, key)); } @Test void getWithTypeSafetyAndInvalidRequiredTypeThrowsException() { Integer key = 42; String value = "enigma"; store.put(namespace, key, value); Exception exception = assertThrows(NamespacedHierarchicalStoreException.class, () -> store.get(namespace, key, Number.class)); assertEquals("Object stored under key [42] is not of required type [java.lang.Number]", exception.getMessage()); } @Test void getWithTypeSafety() { Integer key = 42; String value = "enigma"; store.put(namespace, key, value); // The fact that we can declare this as a String suffices for testing the required type. String requiredTypeValue = store.get(namespace, key, String.class); assertEquals(value, requiredTypeValue); } @Test void getWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; int value = 42; store.put(namespace, key, value); // The fact that we can declare this as an int/Integer suffices for testing the required type. int requiredInt = store.get(namespace, key, int.class); Integer requiredInteger = store.get(namespace, key, Integer.class); assertEquals(value, requiredInt); assertEquals(value, requiredInteger.intValue()); } @Test void getNullValueWithTypeSafety() { store.put(namespace, key, null); // The fact that we can declare this as a String suffices for testing the required type. String requiredTypeValue = store.get(namespace, key, String.class); assertNull(requiredTypeValue); } @Test void getOrComputeIfAbsentWithTypeSafetyAndInvalidRequiredTypeThrowsException() { String key = "pi"; Float value = 3.14f; // Store a Float... store.put(namespace, key, value); // But declare that our function creates a String... Function defaultCreator = k -> "enigma"; Exception exception = assertThrows(NamespacedHierarchicalStoreException.class, () -> store.getOrComputeIfAbsent(namespace, key, defaultCreator, String.class)); assertEquals("Object stored under key [pi] is not of required type [java.lang.String]", exception.getMessage()); } @Test void getOrComputeIfAbsentWithTypeSafety() { Integer key = 42; String value = "enigma"; // The fact that we can declare this as a String suffices for testing the required type. String computedValue = store.getOrComputeIfAbsent(namespace, key, k -> value, String.class); assertEquals(value, computedValue); } @Test void getOrComputeIfAbsentWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; int value = 42; // The fact that we can declare this as an int/Integer suffices for testing the required type. int computedInt = store.getOrComputeIfAbsent(namespace, key, k -> value, int.class); Integer computedInteger = store.getOrComputeIfAbsent(namespace, key, k -> value, Integer.class); assertEquals(value, computedInt); assertEquals(value, computedInteger.intValue()); } @Test void getOrComputeIfAbsentWithExceptionThrowingCreatorFunction() { var e = assertThrows(RuntimeException.class, () -> store.getOrComputeIfAbsent(namespace, key, __ -> { throw new RuntimeException("boom"); })); assertSame(e, assertThrows(RuntimeException.class, () -> store.get(namespace, key))); assertSame(e, assertThrows(RuntimeException.class, () -> store.remove(namespace, key))); } @Test void removeWithTypeSafetyAndInvalidRequiredTypeThrowsException() { Integer key = 42; String value = "enigma"; store.put(namespace, key, value); Exception exception = assertThrows(NamespacedHierarchicalStoreException.class, () -> store.remove(namespace, key, Number.class)); assertEquals("Object stored under key [42] is not of required type [java.lang.Number]", exception.getMessage()); } @Test void removeWithTypeSafety() { Integer key = 42; String value = "enigma"; store.put(namespace, key, value); // The fact that we can declare this as a String suffices for testing the required type. String removedValue = store.remove(namespace, key, String.class); assertEquals(value, removedValue); assertNull(store.get(namespace, key)); } @Test void removeWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; int value = 42; store.put(namespace, key, value); // The fact that we can declare this as an int suffices for testing the required type. int requiredInt = store.remove(namespace, key, int.class); assertEquals(value, requiredInt); store.put(namespace, key, value); // The fact that we can declare this as an Integer suffices for testing the required type. Integer requiredInteger = store.get(namespace, key, Integer.class); assertEquals(value, requiredInteger.intValue()); } @Test void removeNullValueWithTypeSafety() { Integer key = 42; store.put(namespace, key, null); // The fact that we can declare this as a String suffices for testing the required type. String removedValue = store.remove(namespace, key, String.class); assertNull(removedValue); assertNull(store.get(namespace, key)); } @Test void simulateRaceConditionInGetOrComputeIfAbsent() throws Exception { int threads = 10; AtomicInteger counter = new AtomicInteger(); List values; try (var localStore = new NamespacedHierarchicalStore<>(null)) { values = executeConcurrently(threads, // () -> localStore.getOrComputeIfAbsent(namespace, key, it -> counter.incrementAndGet())); } assertEquals(1, counter.get()); assertThat(values).hasSize(threads).containsOnly(1); } } @Nested class InheritedValuesTests { @Test void valueFromParentIsVisible() { parentStore.put(namespace, key, value); assertEquals(value, store.get(namespace, key)); } @Test void valueFromParentCanBeOverriddenInChild() { parentStore.put(namespace, key, value); Object otherValue = new Object(); store.put(namespace, key, otherValue); assertEquals(otherValue, store.get(namespace, key)); assertEquals(value, parentStore.get(namespace, key)); } } @Nested class CompositeNamespaceTests { @Test void additionNamespacePartMakesADifference() { String ns1 = "part1/part2"; String ns2 = "part1"; Object value2 = createObject("value2"); parentStore.put(ns1, key, value); parentStore.put(ns2, key, value2); assertEquals(value, store.get(ns1, key)); assertEquals(value2, store.get(ns2, key)); } } @Nested class CloseActionTests { @Test void callsCloseActionInReverseInsertionOrderWhenClosingStore() throws Throwable { store.put(namespace, "key1", "value1"); store.put(namespace, "key2", "value2"); store.put(namespace, "key3", "value3"); verifyNoInteractions(closeAction); store.close(); var inOrder = inOrder(closeAction); inOrder.verify(closeAction).close(namespace, "key3", "value3"); inOrder.verify(closeAction).close(namespace, "key2", "value2"); inOrder.verify(closeAction).close(namespace, "key1", "value1"); } @Test void doesNotCallCloseActionForRemovedValues() { store.put(namespace, key, value); store.remove(namespace, key); store.close(); verifyNoInteractions(closeAction); } @Test void doesNotCallCloseActionForReplacedValues() throws Throwable { store.put(namespace, key, "value1"); store.put(namespace, key, "value2"); store.close(); verify(closeAction).close(namespace, key, "value2"); verifyNoMoreInteractions(closeAction); } @Test void doesNotCallCloseActionForNullValues() { store.put(namespace, key, null); store.close(); verifyNoInteractions(closeAction); } @Test void ignoresStoredValuesThatThrewExceptionsDuringCleanup() { assertThrows(RuntimeException.class, () -> store.getOrComputeIfAbsent(namespace, key, __ -> { throw new RuntimeException("boom"); })); assertDoesNotThrow(store::close); verifyNoInteractions(closeAction); } @Test void doesNotIgnoreStoredValuesThatThrewUnrecoverableFailuresDuringCleanup() { assertThrows(OutOfMemoryError.class, () -> store.getOrComputeIfAbsent(namespace, key, __ -> { throw new OutOfMemoryError(); })); assertThrows(OutOfMemoryError.class, store::close); verifyNoInteractions(closeAction); } } private Object createObject(final String display) { return new Object() { @Override public String toString() { return display; } }; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/jfr/000077500000000000000000000000001455764576500252275ustar00rootroot00000000000000FlightRecordingDiscoveryListenerIntegrationTests.java000066400000000000000000000033741455764576500377210ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/jfr/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.jfr; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.moditect.jfrunit.ExpectedEvent.event; import static org.moditect.jfrunit.JfrEventsAssert.assertThat; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly; import org.moditect.jfrunit.EnableEvent; import org.moditect.jfrunit.JfrEventTest; import org.moditect.jfrunit.JfrEvents; @JfrEventTest public class FlightRecordingDiscoveryListenerIntegrationTests { public JfrEvents jfrEvents = new JfrEvents(); @Test @EnableEvent("org.junit.*") void reportsEvents() { var launcher = LauncherFactoryForTestingPurposesOnly.createLauncher(new JupiterTestEngine()); var request = request() // .selectors(selectClass(FlightRecordingDiscoveryListenerIntegrationTests.class)) // .listeners(new FlightRecordingDiscoveryListener()) // .build(); launcher.discover(request); jfrEvents.awaitEvents(); assertThat(jfrEvents) // .contains(event("org.junit.LauncherDiscovery") // // TODO JfrUnit does not yey support checking int values // .with("selectors", 1) // // .with("filters", 0) // ) // .contains(event("org.junit.EngineDiscovery") // .with("uniqueId", "[engine:junit-jupiter]")); } } FlightRecordingExecutionListenerIntegrationTests.java000066400000000000000000000051371455764576500377140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/jfr/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.jfr; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.moditect.jfrunit.ExpectedEvent.event; import static org.moditect.jfrunit.JfrEventsAssert.assertThat; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestReporter; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly; import org.moditect.jfrunit.EnableEvent; import org.moditect.jfrunit.JfrEventTest; import org.moditect.jfrunit.JfrEvents; @JfrEventTest public class FlightRecordingExecutionListenerIntegrationTests { public JfrEvents jfrEvents = new JfrEvents(); @Test @EnableEvent("org.junit.*") void reportsEvents() { var launcher = LauncherFactoryForTestingPurposesOnly.createLauncher(new JupiterTestEngine()); var request = request() // .selectors(selectClass(TestCase.class)) // .build(); launcher.execute(request, new FlightRecordingExecutionListener()); jfrEvents.awaitEvents(); assertThat(jfrEvents) // .contains(event("org.junit.TestPlanExecution") // .with("engineNames", "JUnit Jupiter")) // .contains(event("org.junit.TestExecution") // .with("displayName", "JUnit Jupiter") // .with("type", "CONTAINER")) // .contains(event("org.junit.TestExecution") // .with("displayName", FlightRecordingExecutionListenerIntegrationTests.class.getSimpleName() + "$" + TestCase.class.getSimpleName()) // .with("type", "CONTAINER")) // .contains(event("org.junit.TestExecution") // .with("displayName", "test(TestReporter)") // .with("type", "TEST") // .with("result", "SUCCESSFUL")) // .contains(event("org.junit.ReportEntry") // .with("key", "message") // .with("value", "Hello JFR!")) // .contains(event("org.junit.SkippedTest") // .with("displayName", "skipped()") // .with("type", "TEST") // .with("reason", "for demonstration purposes")); } static class TestCase { @Test void test(TestReporter reporter) { reporter.publishEntry("message", "Hello JFR!"); } @Test @Disabled("for demonstration purposes") void skipped() { } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/000077500000000000000000000000001455764576500262475ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/DiscoveryFilterStub.java000066400000000000000000000015031455764576500330640ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import java.util.function.Function; import java.util.function.Supplier; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.FilterResult; /** * @since 1.0 */ public class DiscoveryFilterStub extends FilterStub implements DiscoveryFilter { public DiscoveryFilterStub(String toString) { super(toString); } public DiscoveryFilterStub(Function function, Supplier toString) { super(function, toString); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/FilterStub.java000066400000000000000000000020771455764576500312030ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import java.util.function.Function; import java.util.function.Supplier; import org.junit.platform.engine.Filter; import org.junit.platform.engine.FilterResult; /** * @since 1.0 */ public class FilterStub implements Filter { private final Function function; private final Supplier toString; public FilterStub(String toString) { this(o -> FilterResult.included("always"), () -> toString); } public FilterStub(Function function, Supplier toString) { this.function = function; this.toString = toString; } @Override public FilterResult apply(T object) { return function.apply(object); } @Override public String toString() { return toString.get(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/InterceptedTestEngine.java000066400000000000000000000010711455764576500333450ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import org.junit.platform.fakes.TestEngineSpy; public class InterceptedTestEngine extends TestEngineSpy { public static final String ID = "intercepted-engine"; public InterceptedTestEngine() { super(ID); } } InterceptorInjectedLauncherSessionListener.java000066400000000000000000000021311455764576500375300ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; public class InterceptorInjectedLauncherSessionListener implements LauncherSessionListener { public static int CALLS; public InterceptorInjectedLauncherSessionListener() { assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, Thread.currentThread().getContextClassLoader().getName()); assertTrue(TestLauncherInterceptor2.INTERCEPTING); } @Override public void launcherSessionOpened(LauncherSession session) { CALLS++; } @Override public void launcherSessionClosed(LauncherSession session) { assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, Thread.currentThread().getContextClassLoader().getName()); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/PostDiscoveryFilterStub.java000066400000000000000000000015461455764576500337410ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import java.util.function.Function; import java.util.function.Supplier; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; /** * @since 1.0 */ public class PostDiscoveryFilterStub extends FilterStub implements PostDiscoveryFilter { public PostDiscoveryFilterStub(String toString) { super(toString); } public PostDiscoveryFilterStub(Function function, Supplier toString) { super(function, toString); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/TagFilterTests.java000066400000000000000000000175251455764576500320300ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.launcher.TagFilter.excludeTags; import static org.junit.platform.launcher.TagFilter.includeTags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.DemoClassTestDescriptor; /** * Unit tests for {@link TagFilter}. * *

NOTE: part of the behavior of these tests regarding tags is * influenced by the implementation of {@link DemoClassTestDescriptor#getTags()} * rather than any concrete test engine. * * @since 1.0 */ class TagFilterTests { private static final TestDescriptor classWithTag1 = classTestDescriptor("class1", ClassWithTag1.class); private static final TestDescriptor classWithTag1AndSurroundingWhitespace = classTestDescriptor( "class1-surrounding-whitespace", ClassWithTag1AndSurroundingWhitespace.class); private static final TestDescriptor classWithTag2 = classTestDescriptor("class2", ClassWithTag2.class); private static final TestDescriptor classWithBothTags = classTestDescriptor("class12", ClassWithBothTags.class); private static final TestDescriptor classWithDifferentTags = classTestDescriptor("classX", ClassWithDifferentTags.class); private static final TestDescriptor classWithNoTags = classTestDescriptor("class", ClassWithNoTags.class); @Test void includeTagsWithInvalidSyntax() { // @formatter:off assertAll( () -> assertSyntaxViolationForIncludes(null), () -> assertSyntaxViolationForIncludes(""), () -> assertSyntaxViolationForIncludes(" "), () -> assertSyntaxViolationForIncludes("foo bar") ); // @formatter:on } private void assertSyntaxViolationForIncludes(String tag) { var exception = assertThrows(PreconditionViolationException.class, () -> includeTags(tag)); assertThat(exception).hasMessageStartingWith("Unable to parse tag expression"); } @Test void excludeTagsWithInvalidSyntax() { // @formatter:off assertAll( () -> assertSyntaxViolationForExcludes(null), () -> assertSyntaxViolationForExcludes(""), () -> assertSyntaxViolationForExcludes(" "), () -> assertSyntaxViolationForExcludes("foo bar") ); // @formatter:on } private void assertSyntaxViolationForExcludes(String tag) { var exception = assertThrows(PreconditionViolationException.class, () -> excludeTags(tag)); assertThat(exception).hasMessageStartingWith("Unable to parse tag expression"); } @Test void includeSingleTag() { includeSingleTag(includeTags("tag1")); } @Test void includeSingleTagAndWhitespace() { includeSingleTag(includeTags("\t \n tag1 ")); } @Test void includeMultipleTags() { var filter = includeTags("tag1", " tag2 "); assertTrue(filter.apply(classWithBothTags).included()); assertTrue(filter.apply(classWithTag1).included()); assertTrue(filter.apply(classWithTag1AndSurroundingWhitespace).included()); assertTrue(filter.apply(classWithTag2).included()); assertTrue(filter.apply(classWithDifferentTags).excluded()); assertTrue(filter.apply(classWithNoTags).excluded()); } @Test void excludeSingleTag() { excludeSingleTag(excludeTags("tag1")); } @Test void excludeSingleTagAndWhitespace() { excludeSingleTag(excludeTags("\t \n tag1 ")); } @Test void excludeMultipleTags() { var filter = excludeTags("tag1", " tag2 "); var exclusionReason = "excluded because tags match tag expression(s): [tag1,tag2]"; assertExcluded(filter.apply(classWithTag1), exclusionReason); assertExcluded(filter.apply(classWithTag1AndSurroundingWhitespace), exclusionReason); assertExcluded(filter.apply(classWithBothTags), exclusionReason); assertExcluded(filter.apply(classWithTag2), exclusionReason); var inclusionReason = "included because tags do not match expression(s): [tag1,tag2]"; assertIncluded(filter.apply(classWithDifferentTags), inclusionReason); assertIncluded(filter.apply(classWithNoTags), inclusionReason); } @Test void rejectSingleUnparsableTagExpressions() { var brokenTagExpression = "tag & "; RuntimeException expected = assertThrows(PreconditionViolationException.class, () -> TagFilter.includeTags(brokenTagExpression)); assertThat(expected).hasMessageStartingWith("Unable to parse tag expression \"" + brokenTagExpression + "\""); } @Test void rejectUnparsableTagExpressionFromArray() { var brokenTagExpression = "tag & "; RuntimeException expected = assertThrows(PreconditionViolationException.class, () -> TagFilter.excludeTags(brokenTagExpression, "foo", "bar")); assertThat(expected).hasMessageStartingWith("Unable to parse tag expression \"" + brokenTagExpression + "\""); } private void includeSingleTag(PostDiscoveryFilter filter) { var inclusionReason = "included because tags match expression(s): [tag1]"; assertIncluded(filter.apply(classWithTag1), inclusionReason); assertIncluded(filter.apply(classWithTag1AndSurroundingWhitespace), inclusionReason); assertIncluded(filter.apply(classWithBothTags), inclusionReason); var exclusionReason = "excluded because tags do not match tag expression(s): [tag1]"; assertExcluded(filter.apply(classWithTag2), exclusionReason); assertExcluded(filter.apply(classWithDifferentTags), exclusionReason); assertExcluded(filter.apply(classWithNoTags), exclusionReason); } private void excludeSingleTag(PostDiscoveryFilter filter) { var exclusionReason = "excluded because tags match tag expression(s): [tag1]"; assertExcluded(filter.apply(classWithTag1), exclusionReason); assertExcluded(filter.apply(classWithTag1AndSurroundingWhitespace), exclusionReason); assertExcluded(filter.apply(classWithBothTags), exclusionReason); var inclusionReason = "included because tags do not match expression(s): [tag1]"; assertIncluded(filter.apply(classWithTag2), inclusionReason); assertIncluded(filter.apply(classWithDifferentTags), inclusionReason); assertIncluded(filter.apply(classWithNoTags), inclusionReason); } private void assertIncluded(FilterResult filterResult, String expectedReason) { assertTrue(filterResult.included()); assertThat(filterResult.getReason()).contains(expectedReason); } private void assertExcluded(FilterResult filterResult, String expectedReason) { assertTrue(filterResult.excluded()); assertThat(filterResult.getReason()).contains(expectedReason); } // ------------------------------------------------------------------------- @Retention(RetentionPolicy.RUNTIME) @Tag("tag1") private @interface Tag1 { } @Retention(RetentionPolicy.RUNTIME) @Tag("tag2") private @interface Tag2 { } @Tag1 private static class ClassWithTag1 { } @Tag(" tag1 \t ") private static class ClassWithTag1AndSurroundingWhitespace { } @Tag2 private static class ClassWithTag2 { } @Tag1 @Tag2 private static class ClassWithBothTags { } @Tag("foo") @Tag("bar") private static class ClassWithDifferentTags { } @Tag(" ") // intentionally "blank" private static class ClassWithNoTags { } private static TestDescriptor classTestDescriptor(String uniqueId, Class testClass) { var rootUniqueId = UniqueId.root("class", uniqueId); return new DemoClassTestDescriptor(rootUniqueId, testClass); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/TagIntegrationTests.java000066400000000000000000000064571455764576500330700ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.TagFilter.includeTags; import static org.junit.platform.launcher.TagIntegrationTests.TaggedTestCase.doubleTaggedWasExecuted; import static org.junit.platform.launcher.TagIntegrationTests.TaggedTestCase.tag1WasExecuted; import static org.junit.platform.launcher.TagIntegrationTests.TaggedTestCase.tag2WasExecuted; import static org.junit.platform.launcher.TagIntegrationTests.TaggedTestCase.unTaggedWasExecuted; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.testkit.engine.EngineTestKit; class TagIntegrationTests { @BeforeEach void init() { tag1WasExecuted = false; tag2WasExecuted = false; unTaggedWasExecuted = false; doubleTaggedWasExecuted = false; } @Test void includingWrongTagExecutesNothing() { executeTaggedTestCase(includeTags("whatever")); assertFalse(tag1WasExecuted); assertFalse(tag2WasExecuted); assertFalse(doubleTaggedWasExecuted); assertFalse(unTaggedWasExecuted); } @Test void includingSuitableTagExecutesTaggedTestOnly() { executeTaggedTestCase(includeTags("tag1")); assertTrue(tag1WasExecuted); assertFalse(tag2WasExecuted); assertTrue(doubleTaggedWasExecuted); assertFalse(unTaggedWasExecuted); } @ParameterizedTest @ValueSource(strings = { "any()", "!none()" }) void includingTheAnyKeywordExecutesAllTaggedTests(String tagExpression) { executeTaggedTestCase(includeTags(tagExpression)); assertTrue(tag1WasExecuted); assertTrue(tag2WasExecuted); assertTrue(doubleTaggedWasExecuted); assertFalse(unTaggedWasExecuted); } @ParameterizedTest @ValueSource(strings = { "none()", "!any()" }) void includingTheNoneKeywordExecutesAllUntaggedTests(String tagExpression) { executeTaggedTestCase(includeTags(tagExpression)); assertFalse(tag1WasExecuted); assertFalse(tag2WasExecuted); assertFalse(doubleTaggedWasExecuted); assertTrue(unTaggedWasExecuted); } private void executeTaggedTestCase(PostDiscoveryFilter filter) { EngineTestKit.engine("junit-jupiter") // .selectors(selectClass(TaggedTestCase.class)) // .filters(filter) // .execute(); } static class TaggedTestCase { static boolean tag1WasExecuted = false; static boolean tag2WasExecuted = false; static boolean unTaggedWasExecuted = false; static boolean doubleTaggedWasExecuted = false; @Test @Tag("tag1") void tagged1() { tag1WasExecuted = true; } @Test @Tag("tag2") void tagged2() { tag2WasExecuted = true; } @Test @Tag("tag1") @Tag("tag2") void doubleTagged() { doubleTaggedWasExecuted = true; } @Test void unTagged() { unTaggedWasExecuted = true; } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/TestIdentifierTests.java000066400000000000000000000102411455764576500330550ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.SerializationUtils.deserialize; import static org.junit.platform.commons.util.SerializationUtils.serialize; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestDescriptorStub; /** * @since 1.0 */ class TestIdentifierTests { @Test void inheritsIdAndNamesFromDescriptor() { TestDescriptor testDescriptor = new TestDescriptorStub(UniqueId.root("aType", "uniqueId"), "displayName"); var testIdentifier = TestIdentifier.from(testDescriptor); assertEquals("[aType:uniqueId]", testIdentifier.getUniqueId()); assertEquals("displayName", testIdentifier.getDisplayName()); } @Test void inheritsTypeFromDescriptor() { TestDescriptor descriptor = new TestDescriptorStub(UniqueId.root("aType", "uniqueId"), "displayName"); var identifier = TestIdentifier.from(descriptor); assertEquals(TestDescriptor.Type.TEST, identifier.getType()); assertTrue(identifier.isTest()); assertFalse(identifier.isContainer()); descriptor.addChild(new TestDescriptorStub(UniqueId.root("aChild", "uniqueId"), "displayName")); identifier = TestIdentifier.from(descriptor); assertEquals(TestDescriptor.Type.CONTAINER, identifier.getType()); assertFalse(identifier.isTest()); assertTrue(identifier.isContainer()); } @Test void currentVersionCanBeSerializedAndDeserialized() throws Exception { var originalIdentifier = createOriginalTestIdentifier(); var deserializedIdentifier = (TestIdentifier) deserialize(serialize(originalIdentifier)); assertDeepEquals(originalIdentifier, deserializedIdentifier); } @Test void initialVersionCanBeDeserialized() throws Exception { try (var inputStream = getClass().getResourceAsStream("/serialized-test-identifier")) { var bytes = inputStream.readAllBytes(); var deserializedIdentifier = (TestIdentifier) deserialize(bytes); assertDeepEquals(createOriginalTestIdentifier(), deserializedIdentifier); } } private static void assertDeepEquals(TestIdentifier first, TestIdentifier second) { assertEquals(first, second); assertEquals(first.getUniqueId(), second.getUniqueId()); assertEquals(first.getUniqueIdObject(), second.getUniqueIdObject()); assertEquals(first.getDisplayName(), second.getDisplayName()); assertEquals(first.getLegacyReportingName(), second.getLegacyReportingName()); assertEquals(first.getSource(), second.getSource()); assertEquals(first.getTags(), second.getTags()); assertEquals(first.getType(), second.getType()); assertEquals(first.getParentId(), second.getParentId()); assertEquals(first.getParentIdObject(), second.getParentIdObject()); } private static TestIdentifier createOriginalTestIdentifier() { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var uniqueId = engineDescriptor.getUniqueId().append("child", "child"); var testSource = ClassSource.from(TestIdentifierTests.class); var testDescriptor = new AbstractTestDescriptor(uniqueId, "displayName", testSource) { @Override public Type getType() { return Type.TEST; } @Override public String getLegacyReportingName() { return "reportingName"; } @Override public Set getTags() { return Set.of(TestTag.create("aTag")); } }; engineDescriptor.addChild(testDescriptor); return TestIdentifier.from(testDescriptor); } } TestLauncherDiscoveryListener.java000066400000000000000000000010761455764576500350360ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; public class TestLauncherDiscoveryListener implements LauncherDiscoveryListener { public static boolean called; @Override public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { called = true; } } TestLauncherInterceptor1.java000066400000000000000000000026071455764576500337410ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; import java.net.URLClassLoader; public class TestLauncherInterceptor1 implements LauncherInterceptor { public static final String CLASSLOADER_NAME = "interceptor-loader"; private final ClassLoader originalClassLoader; private final URLClassLoader replacedClassLoader; public TestLauncherInterceptor1() { originalClassLoader = Thread.currentThread().getContextClassLoader(); var url = getClass().getClassLoader().getResource("intercepted-testservices/"); replacedClassLoader = new URLClassLoader(CLASSLOADER_NAME, new URL[] { url }, originalClassLoader); Thread.currentThread().setContextClassLoader(replacedClassLoader); } @Override public T intercept(Invocation invocation) { return invocation.proceed(); } @Override public void close() { try { replacedClassLoader.close(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } } TestLauncherInterceptor2.java000066400000000000000000000012451455764576500337370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; public class TestLauncherInterceptor2 implements LauncherInterceptor { public static boolean INTERCEPTING; @Override public T intercept(Invocation invocation) { INTERCEPTING = true; try { return invocation.proceed(); } finally { INTERCEPTING = false; } } @Override public void close() { } } TestLauncherSessionListener.java000066400000000000000000000012231455764576500345040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; public class TestLauncherSessionListener implements LauncherSessionListener { @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } return getClass() == obj.getClass(); } @Override public int hashCode() { return 1; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/TestPlanTests.java000066400000000000000000000100531455764576500316660ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import java.util.List; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestDescriptorStub; class TestPlanTests { private final ConfigurationParameters configParams = mock(); private final EngineDescriptor engineDescriptor = new EngineDescriptor(UniqueId.forEngine("foo"), "Foo"); @Test void doesNotContainTestsForEmptyContainers() { engineDescriptor.addChild( new AbstractTestDescriptor(engineDescriptor.getUniqueId().append("test", "bar"), "Bar") { @Override public Type getType() { return Type.CONTAINER; } }); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); assertThat(testPlan.containsTests()).as("contains tests").isFalse(); } @Test void containsTestsForTests() { engineDescriptor.addChild( new AbstractTestDescriptor(engineDescriptor.getUniqueId().append("test", "bar"), "Bar") { @Override public Type getType() { return Type.TEST; } }); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); assertThat(testPlan.containsTests()).as("contains tests").isTrue(); } @Test void containsTestsForContainersThatMayRegisterTests() { engineDescriptor.addChild( new AbstractTestDescriptor(engineDescriptor.getUniqueId().append("test", "bar"), "Bar") { @Override public Type getType() { return Type.CONTAINER; } @Override public boolean mayRegisterTests() { return true; } }); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); assertThat(testPlan.containsTests()).as("contains tests").isTrue(); } @Test void acceptsVisitorsInDepthFirstOrder() { var container = new TestDescriptorStub(engineDescriptor.getUniqueId().append("container", "bar"), "Bar"); var test1 = new TestDescriptorStub(container.getUniqueId().append("test", "bar"), "Bar"); container.addChild(test1); engineDescriptor.addChild(container); var engineDescriptor2 = new EngineDescriptor(UniqueId.forEngine("baz"), "Baz"); var test2 = new TestDescriptorStub(engineDescriptor2.getUniqueId().append("test", "baz1"), "Baz"); var test3 = new TestDescriptorStub(engineDescriptor2.getUniqueId().append("test", "baz2"), "Baz"); engineDescriptor2.addChild(test2); engineDescriptor2.addChild(test3); var testPlan = TestPlan.from(List.of(engineDescriptor, engineDescriptor2), configParams); var visitor = mock(TestPlan.Visitor.class); testPlan.accept(visitor); var inOrder = inOrder(visitor); inOrder.verify(visitor).preVisitContainer(TestIdentifier.from(engineDescriptor)); inOrder.verify(visitor).visit(TestIdentifier.from(engineDescriptor)); inOrder.verify(visitor).preVisitContainer(TestIdentifier.from(container)); inOrder.verify(visitor).visit(TestIdentifier.from(container)); inOrder.verify(visitor).visit(TestIdentifier.from(test1)); inOrder.verify(visitor).postVisitContainer(TestIdentifier.from(container)); inOrder.verify(visitor).postVisitContainer(TestIdentifier.from(engineDescriptor)); inOrder.verify(visitor).preVisitContainer(TestIdentifier.from(engineDescriptor2)); inOrder.verify(visitor).visit(TestIdentifier.from(engineDescriptor2)); inOrder.verify(visitor).visit(TestIdentifier.from(test2)); inOrder.verify(visitor).visit(TestIdentifier.from(test3)); inOrder.verify(visitor).postVisitContainer(TestIdentifier.from(engineDescriptor2)); } } TestPostDiscoveryTagFilter.java000066400000000000000000000014231455764576500343120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; public class TestPostDiscoveryTagFilter implements PostDiscoveryFilter { @Override public FilterResult apply(final TestDescriptor object) { var include = object.getTags().stream().map(TestTag::getName).anyMatch("test-post-discovery"::equals); return FilterResult.includedIf(include); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/000077500000000000000000000000001455764576500271775ustar00rootroot00000000000000CompositeEngineExecutionListenerTests.java000066400000000000000000000153341455764576500374760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.DemoMethodTestDescriptor; import org.mockito.InOrder; @TrackLogRecords class CompositeEngineExecutionListenerTests { private final List listeners = new ArrayList<>( List.of(new ThrowingEngineExecutionListener())); @Test void shouldNotThrowExceptionButLogIfDynamicTestRegisteredListenerMethodFails(LogRecordListener logRecordListener) { compositeEngineExecutionListener().dynamicTestRegistered(anyTestDescriptor()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEngineExecutionListener.class, "dynamicTestRegistered"); } @Test void shouldNotThrowExceptionButLogIfExecutionStartedListenerMethodFails(LogRecordListener logRecordListener) { compositeEngineExecutionListener().executionStarted(anyTestDescriptor()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEngineExecutionListener.class, "executionStarted"); } @Test void shouldNotThrowExceptionButLogIfExecutionSkippedListenerMethodFails(LogRecordListener logRecordListener) { compositeEngineExecutionListener().executionSkipped(anyTestDescriptor(), "deliberately skipped container"); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEngineExecutionListener.class, "executionSkipped"); } @Test void shouldNotThrowExceptionButLogIfExecutionFinishedListenerMethodFails(LogRecordListener logRecordListener) { compositeEngineExecutionListener().executionFinished(anyTestDescriptor(), anyTestExecutionResult()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEngineExecutionListener.class, "executionFinished"); } @Test void shouldNotThrowExceptionButLogIfReportingEntryPublishedListenerMethodFails( LogRecordListener logRecordListener) { compositeEngineExecutionListener().reportingEntryPublished(anyTestDescriptor(), ReportEntry.from("one", "two")); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEngineExecutionListener.class, "reportingEntryPublished"); } @Test void shouldThrowOutOfMemoryExceptionAndStopListenerWithoutLog(LogRecordListener logRecordListener) { listeners.clear(); listeners.add(new EngineExecutionListener() { @Override public void executionStarted(TestDescriptor testDescriptor) { throw new OutOfMemoryError(); } }); var testDescriptor = anyTestDescriptor(); assertThatThrownBy(() -> compositeEngineExecutionListener().executionStarted(testDescriptor)).isInstanceOf( OutOfMemoryError.class); assertNotLogs(logRecordListener); } @Test void callsListenersInReverseOrderForFinishedEvents() { listeners.clear(); var firstListener = mock(EngineExecutionListener.class, "firstListener"); var secondListener = mock(EngineExecutionListener.class, "secondListener"); listeners.add(firstListener); listeners.add(secondListener); var testDescriptor = anyTestDescriptor(); var testExecutionResult = anyTestExecutionResult(); var composite = compositeEngineExecutionListener(); composite.executionStarted(testDescriptor); composite.executionFinished(testDescriptor, testExecutionResult); InOrder inOrder = inOrder(firstListener, secondListener); inOrder.verify(firstListener).executionStarted(testDescriptor); inOrder.verify(secondListener).executionStarted(testDescriptor); inOrder.verify(secondListener).executionFinished(testDescriptor, testExecutionResult); inOrder.verify(firstListener).executionFinished(testDescriptor, testExecutionResult); } private EngineExecutionListener compositeEngineExecutionListener() { return new CompositeEngineExecutionListener(listeners); } private LogRecord firstWarnLogRecord(LogRecordListener logRecordListener) throws AssertionError { return logRecordListener.stream(CompositeEngineExecutionListener.class, Level.WARNING).findFirst().orElseThrow( () -> new AssertionError("Failed to find error log record")); } private void assertNotLogs(LogRecordListener logRecordListener) throws AssertionError { assertThat(logRecordListener.stream(CompositeEngineExecutionListener.class, Level.WARNING).count()).isZero(); } private static TestExecutionResult anyTestExecutionResult() { return mock(); } private void assertThatTestListenerErrorLogged(LogRecordListener logRecordListener, Class listenerClass, String methodName) { assertThat(firstWarnLogRecord(logRecordListener).getMessage()).startsWith( "EngineExecutionListener [" + listenerClass.getName() + "] threw exception for method: " + methodName); } private static TestDescriptor anyTestDescriptor() { var testClass = CompositeEngineExecutionListenerTests.class; var method = ReflectionUtils.findMethod(testClass, "anyTestDescriptor", new Class[0]).orElseThrow(); return new DemoMethodTestDescriptor(UniqueId.root("method", "unique_id"), testClass, method); } private static class ThrowingEngineExecutionListener implements EngineExecutionListener { @Override public void dynamicTestRegistered(TestDescriptor testDescriptor) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionStarted(TestDescriptor testDescriptor) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionSkipped(TestDescriptor testDescriptor, String reason) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult) { throw new RuntimeException("failed to invoke listener"); } @Override public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) { throw new RuntimeException("failed to invoke listener"); } } } CompositeTestExecutionListenerTests.java000066400000000000000000000241241455764576500372050ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.DemoMethodTestDescriptor; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.core.CompositeTestExecutionListener.EagerTestExecutionListener; import org.mockito.InOrder; @TrackLogRecords class CompositeTestExecutionListenerTests { private final List listeners = new ArrayList<>(List.of(new ThrowingTestExecutionListener())); @Test void shouldNotThrowExceptionButLogIfDynamicTestRegisteredListenerMethodFails(LogRecordListener logRecordListener) { compositeTestExecutionListener().dynamicTestRegistered(anyTestIdentifier()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "dynamicTestRegistered"); } @Test void shouldNotThrowExceptionButLogIfExecutionStartedListenerMethodFails(LogRecordListener logRecordListener) { compositeTestExecutionListener().executionStarted(anyTestIdentifier()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "executionStarted"); } @Test void shouldNotThrowExceptionButLogIfExecutionSkippedListenerMethodFails(LogRecordListener logRecordListener) { compositeTestExecutionListener().executionSkipped(anyTestIdentifier(), "deliberately skipped container"); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "executionSkipped"); } @Test void shouldNotThrowExceptionButLogIfExecutionFinishedListenerMethodFails(LogRecordListener logRecordListener) { compositeTestExecutionListener().executionFinished(anyTestIdentifier(), anyTestExecutionResult()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "executionFinished"); } @Test void shouldNotThrowExceptionButLogIfReportingEntryPublishedListenerMethodFails( LogRecordListener logRecordListener) { compositeTestExecutionListener().reportingEntryPublished(anyTestIdentifier(), ReportEntry.from("one", "two")); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "reportingEntryPublished"); } @Test void shouldNotThrowExceptionButLogIfTesPlanExecutionStartedListenerMethodFails( LogRecordListener logRecordListener) { compositeTestExecutionListener().testPlanExecutionStarted(anyTestPlan()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "testPlanExecutionStarted"); } @Test void shouldNotThrowExceptionButLogIfTesPlanExecutionFinishedListenerMethodFails( LogRecordListener logRecordListener) { compositeTestExecutionListener().testPlanExecutionFinished(anyTestPlan()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingTestExecutionListener.class, "testPlanExecutionFinished"); } @Test void shouldNotThrowExceptionButLogIfExecutionJustStartedEagerTestListenerMethodFails( LogRecordListener logRecordListener) { listeners.add(new ThrowingEagerTestExecutionListener()); compositeTestExecutionListener().executionStarted(anyTestIdentifier()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEagerTestExecutionListener.class, "executionJustStarted"); } @Test void shouldNotThrowExceptionButLogIfExecutionJustFinishedEagerTestListenerMethodFails( LogRecordListener logRecordListener) { listeners.add(new ThrowingEagerTestExecutionListener()); compositeTestExecutionListener().executionFinished(anyTestIdentifier(), anyTestExecutionResult()); assertThatTestListenerErrorLogged(logRecordListener, ThrowingEagerTestExecutionListener.class, "executionJustFinished"); } @Test void shouldThrowOutOfMemoryExceptionAndStopListenerWithoutLog(LogRecordListener logRecordListener) { listeners.clear(); listeners.add(new TestExecutionListener() { @Override public void executionStarted(TestIdentifier testIdentifier) { throw new OutOfMemoryError(); } }); assertThatThrownBy(() -> compositeTestExecutionListener().executionStarted(anyTestIdentifier())).isInstanceOf( OutOfMemoryError.class); assertNotLogs(logRecordListener); } @Test void shouldThrowOutOfMemoryExceptionAndStopEagerListenerWithoutLog(LogRecordListener logRecordListener) { listeners.add(new EagerTestExecutionListener() { @Override public void executionJustStarted(TestIdentifier testIdentifier) { throw new OutOfMemoryError(); } }); assertThatThrownBy(() -> compositeTestExecutionListener().executionStarted(anyTestIdentifier())).isInstanceOf( OutOfMemoryError.class); assertNotLogs(logRecordListener); } @Test void callsListenersInReverseOrderForFinishedEvents() { listeners.clear(); var firstListener = mock(TestExecutionListener.class, "firstListener"); var secondListener = mock(TestExecutionListener.class, "secondListener"); listeners.add(firstListener); listeners.add(secondListener); var testPlan = anyTestPlan(); var testIdentifier = anyTestIdentifier(); var testExecutionResult = anyTestExecutionResult(); var composite = compositeTestExecutionListener(); composite.testPlanExecutionStarted(testPlan); composite.executionStarted(testIdentifier); composite.executionFinished(testIdentifier, testExecutionResult); composite.testPlanExecutionFinished(testPlan); InOrder inOrder = inOrder(firstListener, secondListener); inOrder.verify(firstListener).testPlanExecutionStarted(testPlan); inOrder.verify(secondListener).testPlanExecutionStarted(testPlan); inOrder.verify(firstListener).executionStarted(testIdentifier); inOrder.verify(secondListener).executionStarted(testIdentifier); inOrder.verify(secondListener).executionFinished(testIdentifier, testExecutionResult); inOrder.verify(firstListener).executionFinished(testIdentifier, testExecutionResult); inOrder.verify(secondListener).testPlanExecutionFinished(testPlan); inOrder.verify(firstListener).testPlanExecutionFinished(testPlan); } private TestExecutionListener compositeTestExecutionListener() { return new CompositeTestExecutionListener(listeners); } private LogRecord firstWarnLogRecord(LogRecordListener logRecordListener) throws AssertionError { return logRecordListener.stream(CompositeTestExecutionListener.class, Level.WARNING).findFirst().orElseThrow( () -> new AssertionError("Failed to find error log record")); } private void assertNotLogs(LogRecordListener logRecordListener) throws AssertionError { assertThat(logRecordListener.stream(CompositeTestExecutionListener.class, Level.WARNING).count()).isZero(); } private static TestExecutionResult anyTestExecutionResult() { return TestExecutionResult.successful(); } private static TestIdentifier anyTestIdentifier() { return TestIdentifier.from(anyTestDescriptor()); } private void assertThatTestListenerErrorLogged(LogRecordListener logRecordListener, Class listenerClass, String methodName) { assertThat(firstWarnLogRecord(logRecordListener).getMessage()).startsWith( "TestExecutionListener [" + listenerClass.getName() + "] threw exception for method: " + methodName); } private static TestPlan anyTestPlan() { return TestPlan.from(Set.of(anyTestDescriptor()), mock()); } private static DemoMethodTestDescriptor anyTestDescriptor() { var testClass = CompositeTestExecutionListenerTests.class; var method = ReflectionUtils.findMethod(testClass, "anyTestDescriptor", new Class[0]).orElseThrow(); return new DemoMethodTestDescriptor(UniqueId.root("method", "unique_id"), testClass, method); } private static class ThrowingEagerTestExecutionListener extends ThrowingTestExecutionListener implements EagerTestExecutionListener { @Override public void executionJustStarted(TestIdentifier testIdentifier) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionJustFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { throw new RuntimeException("failed to invoke listener"); } } private static class ThrowingTestExecutionListener implements TestExecutionListener { @Override public void testPlanExecutionStarted(TestPlan testPlan) { throw new RuntimeException("failed to invoke listener"); } @Override public void testPlanExecutionFinished(TestPlan testPlan) { throw new RuntimeException("failed to invoke listener"); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionStarted(TestIdentifier testIdentifier) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { throw new RuntimeException("failed to invoke listener"); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { throw new RuntimeException("failed to invoke listener"); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { throw new RuntimeException("failed to invoke listener"); } } } DefaultLauncherEngineFilterTests.java000066400000000000000000000166061455764576500363610ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.logging.Level.WARNING; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.EngineFilter.excludeEngines; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * @since 1.0 */ class DefaultLauncherEngineFilterTests { private static final Runnable noOp = () -> { }; @Test void launcherWillNotExecuteEnginesIfNotIncludedByAnEngineFilter() { var firstEngine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("second"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var launcher = createLauncher(firstEngine, secondEngine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId())) .filters(includeEngines("first")) .build()); // @formatter:on assertThat(testPlan.getRoots()).hasSize(1); var rootIdentifier = testPlan.getRoots().iterator().next(); assertThat(testPlan.getChildren(rootIdentifier.getUniqueIdObject())).hasSize(1); assertThat(testPlan.getChildren(UniqueId.forEngine("first"))).hasSize(1); } @Test void launcherWillExecuteAllEnginesExplicitlyIncludedViaSingleEngineFilter() { var firstEngine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("second"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var launcher = createLauncher(firstEngine, secondEngine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId())) .filters(includeEngines("first", "second")) .build()); // @formatter:on assertThat(testPlan.getRoots()).hasSize(2); } @Test void launcherWillNotExecuteEnginesExplicitlyIncludedViaMultipleCompetingEngineFilters() { var firstEngine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("second"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var launcher = createLauncher(firstEngine, secondEngine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId())) .filters(includeEngines("first"), includeEngines("second")) .build()); // @formatter:on assertThat(testPlan.getRoots()).isEmpty(); } @Test void launcherWillNotExecuteEnginesExplicitlyExcludedByAnEngineFilter() { var firstEngine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("second"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var launcher = createLauncher(firstEngine, secondEngine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId())) .filters(excludeEngines("second")) .build()); // @formatter:on assertThat(testPlan.getRoots()).hasSize(1); var rootIdentifier = testPlan.getRoots().iterator().next(); assertThat(testPlan.getChildren(rootIdentifier.getUniqueIdObject())).hasSize(1); assertThat(testPlan.getChildren(UniqueId.forEngine("first"))).hasSize(1); } @Test void launcherWillExecuteEnginesHonoringBothIncludeAndExcludeEngineFilters() { var firstEngine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("second"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var thirdEngine = new DemoHierarchicalTestEngine("third"); TestDescriptor test3 = thirdEngine.addTest("test3", noOp); var launcher = createLauncher(firstEngine, secondEngine, thirdEngine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId()), selectUniqueId(test3.getUniqueId())) .filters(includeEngines("first", "second"), excludeEngines("second")) .build()); // @formatter:on assertThat(testPlan.getRoots()).hasSize(1); var rootIdentifier = testPlan.getRoots().iterator().next(); assertThat(testPlan.getChildren(rootIdentifier.getUniqueIdObject())).hasSize(1); assertThat(testPlan.getChildren(UniqueId.forEngine("first"))).hasSize(1); } @Test @TrackLogRecords void launcherThrowsExceptionWhenNoEngineMatchesIncludeEngineFilter(LogRecordListener log) { var engine = new DemoHierarchicalTestEngine("first"); TestDescriptor test1 = engine.addTest("test1", noOp); LauncherDiscoveryRequest request = request() // .selectors(selectUniqueId(test1.getUniqueId())) // .filters(includeEngines("second")) // .build(); var launcher = createLauncher(engine); var exception = assertThrows(JUnitException.class, () -> launcher.discover(request)); assertThat(exception.getMessage()) // .startsWith("No TestEngine ID matched the following include EngineFilters: [second].") // .contains("Please fix/remove the filter or add the engine.") // .contains("Registered TestEngines:\n- first (") // .endsWith("Registered EngineFilters:\n- EngineFilter that includes engines with IDs [second]"); assertThat(log.stream(WARNING)).isEmpty(); } @Test @TrackLogRecords void launcherWillLogWarningWhenAllEnginesWereExcluded(LogRecordListener log) { var engine = new DemoHierarchicalTestEngine("first"); TestDescriptor test = engine.addTest("test1", noOp); var launcher = createLauncher(engine); // @formatter:off var testPlan = launcher.discover( request() .selectors(selectUniqueId(test.getUniqueId())) .filters(excludeEngines("first")) .build()); // @formatter:on assertThat(testPlan.getRoots()).isEmpty(); assertThat(log.stream(WARNING)).hasSize(1); assertThat(log.stream(WARNING).findAny().orElseThrow().getMessage()) // .startsWith("All TestEngines were excluded by EngineFilters.") // .contains("Registered TestEngines:\n- first (") // .endsWith("Registered EngineFilters:\n- EngineFilter that excludes engines with IDs [first]"); } } DefaultLauncherTests.java000066400000000000000000000644611455764576500340670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.LauncherConstants.DRY_RUN_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestDescriptor; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.fakes.TestEngineSpy; import org.junit.platform.fakes.TestEngineStub; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.launcher.PostDiscoveryFilterStub; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.listeners.SummaryGeneratingListener; import org.mockito.ArgumentCaptor; /** * @since 1.0 */ class DefaultLauncherTests { private static final String FOO = DefaultLauncherTests.class.getSimpleName() + ".foo"; private static final String BAR = DefaultLauncherTests.class.getSimpleName() + ".bar"; private static final Runnable noOp = () -> { }; @Test void constructLauncherWithoutAnyEngines() { var launcher = createLauncher(); Throwable exception = assertThrows(PreconditionViolationException.class, () -> launcher.discover(request().build())); assertThat(exception).hasMessageContaining("Cannot create Launcher without at least one TestEngine"); } @Test void constructLauncherWithMultipleTestEnginesWithDuplicateIds() { var launcher = createLauncher(new DemoHierarchicalTestEngine("dummy id"), new DemoHierarchicalTestEngine("dummy id")); var exception = assertThrows(JUnitException.class, () -> launcher.discover(request().build())); assertThat(exception).hasMessageContaining("multiple engines with the same ID"); } @Test void discoverEmptyTestPlanWithEngineWithoutAnyTests() { var launcher = createLauncher(new DemoHierarchicalTestEngine()); var testPlan = launcher.discover(request().build()); assertThat(testPlan.getRoots()).hasSize(1); } @Test void discoverTestPlanForEngineThatReturnsNullForItsRootDescriptor() { TestEngine engine = new TestEngineStub("some-engine-id") { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { return null; } }; var discoveryListener = mock(LauncherDiscoveryListener.class); var testPlan = createLauncher(engine).discover(request() // .listeners(discoveryListener) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .build()); assertThat(testPlan.getRoots()).hasSize(1); assertDiscoveryFailed(engine, discoveryListener); } @ParameterizedTest @ValueSource(classes = { Error.class, RuntimeException.class }) void discoverErrorTestDescriptorForEngineThatThrowsInDiscoveryPhase(Class throwableClass) { TestEngine engine = new TestEngineStub("my-engine-id") { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { try { var constructor = throwableClass.getDeclaredConstructor(String.class); throw ExceptionUtils.throwAsUncheckedException(constructor.newInstance("ignored")); } catch (Exception ignored) { return null; } } }; var launcher = createLauncher(engine); var discoveryListener = mock(LauncherDiscoveryListener.class); var request = request() // .listeners(discoveryListener) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .build(); var testPlan = launcher.discover(request); assertThat(testPlan.getRoots()).hasSize(1); var engineIdentifier = getOnlyElement(testPlan.getRoots()); assertThat(getOnlyElement(testPlan.getRoots()).getDisplayName()).isEqualTo("my-engine-id"); verify(discoveryListener).launcherDiscoveryStarted(request); verify(discoveryListener).launcherDiscoveryFinished(request); assertDiscoveryFailed(engine, discoveryListener); var listener = mock(TestExecutionListener.class); launcher.execute(testPlan, listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(engineIdentifier); verify(listener).executionFinished(eq(engineIdentifier), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'my-engine-id' failed to discover tests"); } private void assertDiscoveryFailed(TestEngine testEngine, LauncherDiscoveryListener discoveryListener) { var engineId = testEngine.getId(); var failureCaptor = ArgumentCaptor.forClass(EngineDiscoveryResult.class); verify(discoveryListener).engineDiscoveryFinished(eq(UniqueId.forEngine(engineId)), failureCaptor.capture()); var result = failureCaptor.getValue(); assertThat(result.getStatus()).isEqualTo(EngineDiscoveryResult.Status.FAILED); assertThat(result.getThrowable()).isPresent(); assertThat(result.getThrowable().get()).hasMessage( "TestEngine with ID '" + engineId + "' failed to discover tests"); } @Test void reportsEngineExecutionFailuresWithoutPriorEvents() { var rootCause = new RuntimeException("something went horribly wrong"); var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { throw rootCause; } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'TestEngineStub' failed to execute tests") // .hasCauseReference(rootCause); } @Test void reportsEngineExecutionFailuresForSkippedEngine() { var rootCause = new RuntimeException("something went horribly wrong"); var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); request.getEngineExecutionListener().executionSkipped(engineDescriptor, "not today"); throw rootCause; } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'TestEngineStub' failed to execute tests") // .hasCauseReference(rootCause); } @Test void reportsEngineExecutionFailuresForStartedEngine() { var rootCause = new RuntimeException("something went horribly wrong"); var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); request.getEngineExecutionListener().executionStarted(engineDescriptor); throw rootCause; } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'TestEngineStub' failed to execute tests") // .hasCauseReference(rootCause); } @Test void reportsEngineExecutionFailuresForSuccessfullyFinishedEngine() { var rootCause = new RuntimeException("something went horribly wrong"); var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); request.getEngineExecutionListener().executionStarted(engineDescriptor); request.getEngineExecutionListener().executionFinished(engineDescriptor, TestExecutionResult.successful()); throw rootCause; } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'TestEngineStub' failed to execute tests") // .hasCauseReference(rootCause); } @Test void reportsEngineExecutionFailuresForFailedFinishedEngine() { var rootCause = new RuntimeException("something went horribly wrong"); var originalFailure = new RuntimeException("suppressed"); var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); var listener = request.getEngineExecutionListener(); listener.executionStarted(engineDescriptor); listener.executionFinished(engineDescriptor, TestExecutionResult.failed(originalFailure)); throw rootCause; } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); var testExecutionResult = ArgumentCaptor.forClass(TestExecutionResult.class); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), testExecutionResult.capture()); assertThat(testExecutionResult.getValue().getThrowable()).isPresent(); assertThat(testExecutionResult.getValue().getThrowable().get()) // .hasMessage("TestEngine with ID 'TestEngineStub' failed to execute tests") // .hasCauseReference(rootCause) // .hasSuppressedException(originalFailure); } @Test void reportsSkippedEngines() { var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); request.getEngineExecutionListener().executionSkipped(engineDescriptor, "not today"); } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); verify(listener).executionSkipped(any(TestIdentifier.class), eq("not today")); verify(listener, times(0)).executionStarted(any()); verify(listener, times(0)).executionFinished(any(), any()); } @Test void reportsFinishedEngines() { var engine = new TestEngineStub() { @Override public void execute(ExecutionRequest request) { var engineDescriptor = request.getRootTestDescriptor(); var listener = request.getEngineExecutionListener(); listener.executionStarted(engineDescriptor); listener.executionFinished(engineDescriptor, TestExecutionResult.successful()); } }; var listener = mock(TestExecutionListener.class); createLauncher(engine).execute(request().build(), listener); verify(listener).executionStarted(any()); verify(listener).executionFinished(any(), eq(TestExecutionResult.successful())); } @Test void discoverTestPlanForSingleEngine() { var engine = new DemoHierarchicalTestEngine("myEngine"); engine.addTest("test1", noOp); engine.addTest("test2", noOp); var launcher = createLauncher(engine); var testPlan = launcher.discover(request().selectors(selectPackage("any")).build()); assertThat(testPlan.getRoots()).hasSize(1); var rootIdentifier = testPlan.getRoots().iterator().next(); assertThat(testPlan.getChildren(rootIdentifier.getUniqueIdObject())).hasSize(2); assertThat(testPlan.getChildren(UniqueId.parse("[engine:myEngine]"))).hasSize(2); } @Test void discoverTestPlanForMultipleEngines() { var firstEngine = new DemoHierarchicalTestEngine("engine1"); TestDescriptor test1 = firstEngine.addTest("test1", noOp); var secondEngine = new DemoHierarchicalTestEngine("engine2"); TestDescriptor test2 = secondEngine.addTest("test2", noOp); var launcher = createLauncher(firstEngine, secondEngine); var testPlan = launcher.discover( request().selectors(selectUniqueId(test1.getUniqueId()), selectUniqueId(test2.getUniqueId())).build()); assertThat(testPlan.getRoots()).hasSize(2); assertThat(testPlan.getChildren(UniqueId.forEngine("engine1"))).hasSize(1); assertThat(testPlan.getChildren(UniqueId.forEngine("engine2"))).hasSize(1); } @Test void launcherAppliesPostDiscoveryFilters() { var engine = new DemoHierarchicalTestEngine("myEngine"); var test1 = engine.addTest("test1", noOp); engine.addTest("test2", noOp); var launcher = createLauncher(engine); PostDiscoveryFilter includeWithUniqueIdContainsTest = new PostDiscoveryFilterStub( descriptor -> FilterResult.includedIf(descriptor.getUniqueId().toString().contains("test")), () -> "filter1"); PostDiscoveryFilter includeWithUniqueIdContains1 = new PostDiscoveryFilterStub( descriptor -> FilterResult.includedIf(descriptor.getUniqueId().toString().contains("1")), () -> "filter2"); var testPlan = launcher.discover( // request() // .selectors(selectPackage("any")) // .filters(includeWithUniqueIdContainsTest, includeWithUniqueIdContains1) // .build()); assertThat(testPlan.getChildren(UniqueId.forEngine("myEngine"))).hasSize(1); assertThat(testPlan.getTestIdentifier(test1.getUniqueId())).isNotNull(); } @Test @SuppressWarnings("deprecation") void withoutConfigurationParameters_LauncherPassesEmptyConfigurationParametersIntoTheExecutionRequest() { var engine = new TestEngineSpy(); var launcher = createLauncher(engine); launcher.execute(request().build()); var configurationParameters = engine.requestForExecution.getConfigurationParameters(); assertThat(configurationParameters.get("key")).isNotPresent(); assertThat(configurationParameters.size()).isEqualTo(0); } @Test @SuppressWarnings("deprecation") void withConfigurationParameters_LauncherPassesPopulatedConfigurationParametersIntoTheExecutionRequest() { var engine = new TestEngineSpy(); var launcher = createLauncher(engine); launcher.execute(request().configurationParameter("key", "value").build()); var configurationParameters = engine.requestForExecution.getConfigurationParameters(); assertThat(configurationParameters.size()).isEqualTo(1); assertThat(configurationParameters.get("key")).isPresent(); assertThat(configurationParameters.get("key")).contains("value"); } @Test @SuppressWarnings("deprecation") void withoutConfigurationParameters_LookupFallsBackToSystemProperty() { System.setProperty(FOO, BAR); try { var engine = new TestEngineSpy(); var launcher = createLauncher(engine); launcher.execute(request().build()); var configurationParameters = engine.requestForExecution.getConfigurationParameters(); assertThat(configurationParameters.size()).isEqualTo(0); var optionalFoo = configurationParameters.get(FOO); assertTrue(optionalFoo.isPresent(), "foo should have been picked up via system property"); assertEquals(BAR, optionalFoo.get(), "foo property"); } finally { System.clearProperty(FOO); } } @Test void withAdditionalListener() { var engine = new TestEngineSpy(); var listener = new SummaryGeneratingListener(); var launcher = createLauncher(engine); launcher.execute(request().build(), listener); assertThat(listener.getSummary()).isNotNull(); assertThat(listener.getSummary().getContainersFoundCount()).isEqualTo(1); assertThat(listener.getSummary().getTestsFoundCount()).isEqualTo(1); } @Test void prunesTestDescriptorsAfterApplyingPostDiscoveryFilters() { var engine = new TestEngineSpy() { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { super.discover(discoveryRequest, uniqueId); var engineDescriptor = new TestDescriptorStub(uniqueId, uniqueId.toString()); var containerDescriptor = new TestDescriptorStub(uniqueId.append("container", "a"), "container") { @Override public Type getType() { return Type.CONTAINER; } }; containerDescriptor.addChild( new TestDescriptorStub(containerDescriptor.getUniqueId().append("test", "b"), "test")); engineDescriptor.addChild(containerDescriptor); return engineDescriptor; } }; var launcher = createLauncher(engine); var testPlan = launcher.discover(request().filters( (PostDiscoveryFilter) testDescriptor -> FilterResult.includedIf(testDescriptor.isContainer())).build()); assertThat(testPlan.getRoots()).hasSize(1); var engineIdentifier = getOnlyElement(testPlan.getRoots()); assertThat(testPlan.getChildren(engineIdentifier)).isEmpty(); } @Test void reportsDynamicTestDescriptorsCorrectly() { var engineId = UniqueId.forEngine("engine"); var containerAndTestId = engineId.append("c&t", "c&t"); var dynamicTestId = containerAndTestId.append("test", "test"); var engine = new TestEngineSpy(engineId.getLastSegment().getValue()) { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { super.discover(discoveryRequest, uniqueId); var engineDescriptor = new TestDescriptorStub(uniqueId, uniqueId.toString()); engineDescriptor.addChild(new TestDescriptorStub(containerAndTestId, "c&t") { @Override public Type getType() { return Type.CONTAINER_AND_TEST; } }); return engineDescriptor; } @Override public void execute(ExecutionRequest request) { super.execute(request); var listener = request.getEngineExecutionListener(); listener.executionStarted(request.getRootTestDescriptor()); var containerAndTest = getOnlyElement(request.getRootTestDescriptor().getChildren()); listener.executionStarted(containerAndTest); var dynamicTest = new TestDescriptorStub(dynamicTestId, "test"); dynamicTest.setParent(containerAndTest); listener.dynamicTestRegistered(dynamicTest); listener.executionStarted(dynamicTest); listener.executionFinished(dynamicTest, successful()); listener.executionFinished(containerAndTest, successful()); listener.executionFinished(request.getRootTestDescriptor(), successful()); } }; var launcher = createLauncher(engine); var listener = mock(TestExecutionListener.class); launcher.execute(request().build(), listener); var inOrder = inOrder(listener); var testPlanArgumentCaptor = ArgumentCaptor.forClass(TestPlan.class); inOrder.verify(listener).testPlanExecutionStarted(testPlanArgumentCaptor.capture()); var testPlan = testPlanArgumentCaptor.getValue(); var engineTestIdentifier = testPlan.getTestIdentifier(engineId); var containerAndTestIdentifier = testPlan.getTestIdentifier(containerAndTestId); var dynamicTestIdentifier = testPlan.getTestIdentifier(dynamicTestId); assertThat(engineTestIdentifier.getParentIdObject()).isEmpty(); assertThat(containerAndTestIdentifier.getParentIdObject()).contains(engineId); assertThat(dynamicTestIdentifier.getParentIdObject()).contains(containerAndTestId); inOrder.verify(listener).executionStarted(engineTestIdentifier); inOrder.verify(listener).executionStarted(containerAndTestIdentifier); inOrder.verify(listener).dynamicTestRegistered(dynamicTestIdentifier); inOrder.verify(listener).executionStarted(dynamicTestIdentifier); inOrder.verify(listener).executionFinished(dynamicTestIdentifier, successful()); inOrder.verify(listener).executionFinished(containerAndTestIdentifier, successful()); inOrder.verify(listener).executionFinished(engineTestIdentifier, successful()); inOrder.verify(listener).testPlanExecutionFinished(same(testPlan)); } @Test void launcherCanExecuteTestPlanExactlyOnce() { var engine = mock(TestEngine.class); when(engine.getId()).thenReturn("some-engine"); when(engine.discover(any(), any())).thenAnswer(invocation -> { UniqueId uniqueId = invocation.getArgument(1); return new EngineDescriptor(uniqueId, uniqueId.toString()); }); var launcher = createLauncher(engine); var testPlan = launcher.discover(request().build()); verify(engine, times(1)).discover(any(), any()); launcher.execute(testPlan); verify(engine, times(1)).execute(any()); var e = assertThrows(PreconditionViolationException.class, () -> launcher.execute(testPlan)); assertEquals(e.getMessage(), "TestPlan must only be executed once"); } @Test @SuppressWarnings("deprecation") void testPlanThrowsExceptionWhenModified() { TestEngine engine = new TestEngineSpy(); var launcher = createLauncher(engine); var testPlan = launcher.discover(request().build()); var engineIdentifier = getOnlyElement(testPlan.getRoots()); var engineUniqueId = engineIdentifier.getUniqueIdObject(); assertThat(testPlan.getChildren(engineIdentifier)).hasSize(1); var addedIdentifier = TestIdentifier.from( new TestDescriptorStub(engineUniqueId.append("test", "test2"), "test2")); var exception = assertThrows(JUnitException.class, () -> testPlan.add(addedIdentifier)); assertThat(exception).hasMessage("Unsupported attempt to modify the TestPlan was detected. " + "Please contact your IDE/tool vendor and request a fix or downgrade to JUnit 5.7.x (see https://github.com/junit-team/junit5/issues/1732 for details)."); assertThat(testPlan.getChildren(engineIdentifier)).hasSize(1).doesNotContain(addedIdentifier); } @Test @TrackLogRecords void thirdPartyEngineUsingReservedEngineIdPrefixEmitsWarning(LogRecordListener listener) { var id = "junit-using-reserved-prefix"; var launcher = createLauncher(new TestEngineStub(id)); launcher.discover(request().build()); assertThat(listener.stream(EngineIdValidator.class, Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '" + id + "'"); } @Test void thirdPartyEngineClaimingToBeJupiterResultsInException() { assertImposter("junit-jupiter"); } @Test void thirdPartyEngineClaimingToBeVintageResultsInException() { assertImposter("junit-vintage"); } private void assertImposter(String id) { TestEngine impostor = new TestEngineStub(id); var launcher = createLauncher(impostor); Exception exception = assertThrows(JUnitException.class, () -> launcher.discover(request().build())); assertThat(exception).hasMessage( "Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.", impostor.getClass().getName(), id); } @Test void dryRunModeReportsEventsForAllTestsButDoesNotExecuteThem() { var engine = new DemoHierarchicalTestEngine("engine"); var container = engine.addContainer("container", "Container", null); var test = new DemoHierarchicalTestDescriptor(container.getUniqueId().append("test", "test"), "Test", (__, ___) -> { throw new RuntimeException("boom"); }); container.addChild(test); var launcher = createLauncher(engine); TestExecutionListener listener = mock(); launcher.execute(request().configurationParameter(DRY_RUN_PROPERTY_NAME, "true").build(), listener); var inOrder = inOrder(listener); inOrder.verify(listener).testPlanExecutionStarted(any()); inOrder.verify(listener).executionStarted(TestIdentifier.from(engine.getEngineDescriptor())); inOrder.verify(listener).executionStarted(TestIdentifier.from(container)); inOrder.verify(listener).executionSkipped(TestIdentifier.from(test), "JUnit Platform dry-run mode is enabled"); inOrder.verify(listener).executionFinished(TestIdentifier.from(container), successful()); inOrder.verify(listener).executionFinished(TestIdentifier.from(engine.getEngineDescriptor()), successful()); inOrder.verify(listener).testPlanExecutionFinished(any()); inOrder.verifyNoMoreInteractions(); } } EngineDiscoveryResultValidatorTests.java000066400000000000000000000067551455764576500371650ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.fakes.TestEngineStub; /** * @since 1.3 */ class EngineDiscoveryResultValidatorTests { private final TestEngine testEngine = new TestEngineStub("my-engine"); private final EngineDiscoveryResultValidator validator = new EngineDiscoveryResultValidator(); @Test void detectCycleWithDoubleRoot() { var root = new TestDescriptorStub(UniqueId.forEngine("root"), "root"); validator.validate(testEngine, root); root.addChild(root); assertThatThrownBy(() -> validator.validate(testEngine, root)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage(""" The discover() method for TestEngine with ID 'my-engine' returned a cyclic graph; \ [engine:root] exists in at least two paths: (1) [engine:root] (2) [engine:root] -> [engine:root]"""); } @Test void detectCycleWithDoubleGroup() { var rootId = UniqueId.forEngine("root"); var root = new TestDescriptorStub(rootId, "root"); TestDescriptor group1 = new TestDescriptorStub(rootId.append("group", "1"), "1"); TestDescriptor group2 = new TestDescriptorStub(rootId.append("group", "2"), "2"); root.addChild(group1); root.addChild(group2); validator.validate(testEngine, root); group2.addChild(group1); assertThatThrownBy(() -> validator.validate(testEngine, root)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage(""" The discover() method for TestEngine with ID 'my-engine' returned a cyclic graph; \ [engine:root]/[group:1] exists in at least two paths: (1) [engine:root] -> [engine:root]/[group:1] (2) [engine:root] -> [engine:root]/[group:2] -> [engine:root]/[group:1]"""); } @Test void detectCycleWithDoubleTest() { var rootId = UniqueId.forEngine("root"); var root = new TestDescriptorStub(rootId, "root"); TestDescriptor group1 = new TestDescriptorStub(rootId.append("group", "1"), "1"); TestDescriptor group2 = new TestDescriptorStub(rootId.append("group", "2"), "2"); root.addChild(group1); root.addChild(group2); TestDescriptor test1 = new TestDescriptorStub(group1.getUniqueId().append("test", "1"), "1-1"); TestDescriptor test2 = new TestDescriptorStub(group2.getUniqueId().append("test", "2"), "2-2"); group1.addChild(test1); group2.addChild(test2); validator.validate(testEngine, root); group2.addChild(test1); assertThatThrownBy(() -> validator.validate(testEngine, root)) // .isInstanceOf(PreconditionViolationException.class) // .hasMessage(""" The discover() method for TestEngine with ID 'my-engine' returned a cyclic graph; \ [engine:root]/[group:1]/[test:1] exists in at least two paths: (1) [engine:root] -> [engine:root]/[group:1] -> [engine:root]/[group:1]/[test:1] (2) [engine:root] -> [engine:root]/[group:2] -> [engine:root]/[group:1]/[test:1]"""); } } ExecutionListenerAdapterTests.java000066400000000000000000000047241455764576500357670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.DemoMethodTestDescriptor; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; /** * @since 1.0 */ // TODO Test other adapter methods. class ExecutionListenerAdapterTests { @Test void testReportingEntryPublished() { var testDescriptor = getSampleMethodTestDescriptor(); var discoveryResult = new LauncherDiscoveryResult(Map.of(mock(), testDescriptor), mock()); var testPlan = InternalTestPlan.from(discoveryResult); var testIdentifier = testPlan.getTestIdentifier(testDescriptor.getUniqueId()); //not yet spyable with mockito? -> https://github.com/mockito/mockito/issues/146 var testExecutionListener = new MockTestExecutionListener(); var executionListenerAdapter = new ExecutionListenerAdapter(testPlan, testExecutionListener); var entry = ReportEntry.from("one", "two"); executionListenerAdapter.reportingEntryPublished(testDescriptor, entry); assertThat(testExecutionListener.entry).isEqualTo(entry); assertThat(testExecutionListener.testIdentifier).isEqualTo(testIdentifier); } private TestDescriptor getSampleMethodTestDescriptor() { var localMethodNamedNothing = ReflectionUtils.findMethod(this.getClass(), "nothing", new Class[0]).get(); return new DemoMethodTestDescriptor(UniqueId.root("method", "unique_id"), this.getClass(), localMethodNamedNothing); } //for reflection purposes only void nothing() { } static class MockTestExecutionListener implements TestExecutionListener { public TestIdentifier testIdentifier; public ReportEntry entry; @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { this.testIdentifier = testIdentifier; this.entry = entry; } } } LauncherConfigTests.java000066400000000000000000000112451455764576500337000ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.TestEngine; import org.junit.platform.fakes.TestEngineStub; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; /** * Unit tests for {@link LauncherConfig} and {@link LauncherConfig.Builder}. * * @since 1.3 */ class LauncherConfigTests { @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> LauncherConfig.builder().addTestEngines((TestEngine[]) null)); assertThrows(PreconditionViolationException.class, () -> LauncherConfig.builder().addTestExecutionListeners((TestExecutionListener[]) null)); TestEngine engine = new TestEngineStub(); var listener = new TestExecutionListener() { }; assertThrows(PreconditionViolationException.class, () -> LauncherConfig.builder().addTestEngines(engine, engine, null)); assertThrows(PreconditionViolationException.class, () -> LauncherConfig.builder().addTestExecutionListeners(listener, listener, null)); } @Test void defaultConfig() { var config = LauncherConfig.DEFAULT; assertTrue(config.isTestEngineAutoRegistrationEnabled(), "Test engine auto-registration should be enabled by default"); assertTrue(config.isLauncherDiscoveryListenerAutoRegistrationEnabled(), "Launcher discovery listener auto-registration should be enabled by default"); assertTrue(config.isTestExecutionListenerAutoRegistrationEnabled(), "Test execution listener auto-registration should be enabled by default"); assertTrue(config.isPostDiscoveryFilterAutoRegistrationEnabled(), "Post-discovery filter auto-registration should be enabled by default"); assertThat(config.getAdditionalTestEngines()).isEmpty(); assertThat(config.getAdditionalTestExecutionListeners()).isEmpty(); } @Test void disableTestEngineAutoRegistration() { var config = LauncherConfig.builder().enableTestEngineAutoRegistration(false).build(); assertFalse(config.isTestEngineAutoRegistrationEnabled()); } @Test void disableLauncherDiscoveryListenerAutoRegistration() { var config = LauncherConfig.builder().enableLauncherDiscoveryListenerAutoRegistration(false).build(); assertFalse(config.isLauncherDiscoveryListenerAutoRegistrationEnabled()); } @Test void disableTestExecutionListenerAutoRegistration() { var config = LauncherConfig.builder().enableTestExecutionListenerAutoRegistration(false).build(); assertFalse(config.isTestExecutionListenerAutoRegistrationEnabled()); } @Test void disablePostDiscoveryFilterAutoRegistration() { var config = LauncherConfig.builder().enablePostDiscoveryFilterAutoRegistration(false).build(); assertFalse(config.isPostDiscoveryFilterAutoRegistrationEnabled()); } @Test void addTestEngines() { TestEngine first = new TestEngineStub(); TestEngine second = new TestEngineStub(); var config = LauncherConfig.builder().addTestEngines(first, second).build(); assertThat(config.getAdditionalTestEngines()).containsOnly(first, second); } @Test void addLauncherSessionListeners() { var first = new LauncherSessionListener() { }; var second = new LauncherSessionListener() { }; var config = LauncherConfig.builder().addLauncherSessionListeners(first, second).build(); assertThat(config.getAdditionalLauncherSessionListeners()).containsOnly(first, second); } @Test void addLauncherDiscoveryListeners() { var first = new LauncherDiscoveryListener() { }; var second = new LauncherDiscoveryListener() { }; var config = LauncherConfig.builder().addLauncherDiscoveryListeners(first, second).build(); assertThat(config.getAdditionalLauncherDiscoveryListeners()).containsOnly(first, second); } @Test void addTestExecutionListeners() { var first = new TestExecutionListener() { }; var second = new TestExecutionListener() { }; var config = LauncherConfig.builder().addTestExecutionListeners(first, second).build(); assertThat(config.getAdditionalTestExecutionListeners()).containsOnly(first, second); } } LauncherConfigurationParametersTests.java000066400000000000000000000206621455764576500373310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.listeners.SummaryGeneratingListener; /** * Unit tests for {@link LauncherConfigurationParameters}. * * @since 1.0 */ @SuppressWarnings("deprecation") class LauncherConfigurationParametersTests { private static final String CONFIG_FILE_NAME = "test-junit-platform.properties"; private static final String KEY = LauncherConfigurationParametersTests.class.getName(); private static final String INHERITED_PARAM = "parent config param"; private static final String CONFIG_PARAM = "explicit config param"; private static final String CONFIG_FILE = "from config file"; private static final String SYSTEM_PROPERTY = "system property"; @BeforeEach @AfterEach void reset() { System.clearProperty(KEY); } @Test void constructorPreconditions() { assertThrows(PreconditionViolationException.class, () -> fromMap(null)); assertThrows(PreconditionViolationException.class, () -> fromMapAndFile(Map.of(), null)); assertThrows(PreconditionViolationException.class, () -> fromMapAndFile(Map.of(), "")); assertThrows(PreconditionViolationException.class, () -> fromMapAndFile(Map.of(), " ")); } @Test void getPreconditions() { ConfigurationParameters configParams = fromMap(Map.of()); assertThrows(PreconditionViolationException.class, () -> configParams.get(null)); assertThrows(PreconditionViolationException.class, () -> configParams.get("")); assertThrows(PreconditionViolationException.class, () -> configParams.get(" ")); } @Test void noConfigParams() { ConfigurationParameters configParams = fromMap(Map.of()); assertThat(configParams.size()).isEqualTo(0); assertThat(configParams.get(KEY)).isEmpty(); assertThat(configParams.keySet()).doesNotContain(KEY); assertThat(configParams.toString()).doesNotContain(KEY); } @Test void explicitConfigParam() { ConfigurationParameters configParams = fromMap(Map.of(KEY, CONFIG_PARAM)); assertThat(configParams.get(KEY)).contains(CONFIG_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_PARAM); } @Test void systemProperty() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = fromMap(Map.of()); assertThat(configParams.get(KEY)).contains(SYSTEM_PROPERTY); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).doesNotContain(KEY); } @Test void configFile() { ConfigurationParameters configParams = fromMapAndFile(Map.of(), CONFIG_FILE_NAME); assertThat(configParams.get(KEY)).contains(CONFIG_FILE); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_FILE); } @Test void inherited() { ConfigurationParameters configParams = fromMapAndParent( // Map.of(), // Map.of(KEY, INHERITED_PARAM)); assertThat(configParams.get(KEY)).contains(INHERITED_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(KEY); } @Test void explicitConfigParamOverridesSystemProperty() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = fromMap(Map.of(KEY, CONFIG_PARAM)); assertThat(configParams.get(KEY)).contains(CONFIG_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_PARAM); } @Test void explicitConfigParamOverridesConfigFile() { ConfigurationParameters configParams = fromMapAndFile(Map.of(KEY, CONFIG_PARAM), CONFIG_FILE_NAME); assertThat(configParams.get(KEY)).contains(CONFIG_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_PARAM); } @Test void explicitConfigParamOverridesInheritedProperty() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = fromMapAndParent( // Map.of(KEY, CONFIG_PARAM), // Map.of(KEY, INHERITED_PARAM)); assertThat(configParams.get(KEY)).contains(CONFIG_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_PARAM); } @Test void systemPropertyOverridesConfigFile() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = fromMapAndFile(Map.of(), CONFIG_FILE_NAME); assertThat(configParams.get(KEY)).contains(SYSTEM_PROPERTY); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(CONFIG_FILE); } @Test void inheritedPropertyOverridesSystemProperty() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = fromMapAndParent(Map.of(), Map.of(KEY, INHERITED_PARAM)); assertThat(configParams.get(KEY)).contains(INHERITED_PARAM); assertThat(configParams.keySet()).contains(KEY); assertThat(configParams.toString()).contains(KEY); } @Test void getValueInExtensionContext() { var request = LauncherDiscoveryRequestBuilder.request() // .configurationParameter("thing", "one else!") // .selectors(DiscoverySelectors.selectClass(Something.class)).build(); var summary = new SummaryGeneratingListener(); LauncherFactory.create().execute(request, summary); assertEquals(0, summary.getSummary().getTestsFailedCount()); } @Test void getWithSuccessfulTransformer() { ConfigurationParameters configParams = fromMap(Map.of(KEY, "42")); assertThat(configParams.get(KEY, Integer::valueOf)).contains(42); } @Test void getWithErroneousTransformer() { ConfigurationParameters configParams = fromMap(Map.of(KEY, "42")); var exception = assertThrows(JUnitException.class, () -> configParams.get(KEY, input -> { throw new RuntimeException("foo"); })); assertThat(exception).hasMessageContaining( "Failed to transform configuration parameter with key '" + KEY + "' and initial value '42'"); } @Test void ignoresSystemPropertyAndConfigFileWhenImplicitLookupsAreDisabled() { System.setProperty(KEY, SYSTEM_PROPERTY); ConfigurationParameters configParams = LauncherConfigurationParameters.builder() // .enableImplicitProviders(false) // .build(); assertThat(configParams.get(KEY)).isEmpty(); } private static LauncherConfigurationParameters fromMap(Map map) { return LauncherConfigurationParameters.builder().explicitParameters(map).build(); } private static LauncherConfigurationParameters fromMapAndFile(Map map, String configFileName) { return LauncherConfigurationParameters.builder() // .explicitParameters(map) // .configFileName(configFileName) // .build(); } private static LauncherConfigurationParameters fromMapAndParent(Map map, Map inherited) { var parameters = LauncherConfigurationParameters.builder() // .explicitParameters(inherited) // .build(); return LauncherConfigurationParameters.builder() // .explicitParameters(map) // .parentConfigurationParameters(parameters) // .build(); } private static class Mutator implements TestInstancePostProcessor { @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { var value = context.getConfigurationParameter("thing").orElse("thing"); Something.class.getField("thing").set(testInstance, value); } } @ExtendWith(Mutator.class) static class Something { // `public` is needed for simple "Class#getField(String)" to work public String thing = "body."; @Test void some() { assertEquals("Someone else!", "Some" + thing); } } } LauncherDiscoveryRequestBuilderTests.java000066400000000000000000000303121455764576500373160ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.FilterResult.excluded; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectModule; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners.abortOnFailure; import static org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners.logging; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.fakes.TestEngineStub; import org.junit.platform.launcher.DiscoveryFilterStub; import org.junit.platform.launcher.PostDiscoveryFilterStub; /** * @since 1.0 */ class LauncherDiscoveryRequestBuilderTests { @Nested class DiscoverySelectionTests { @Test void modulesAreStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .selectors( selectModule("java.base") ).build(); // @formatter:on var packageSelectors = discoveryRequest.getSelectorsByType(ModuleSelector.class).stream().map( ModuleSelector::getModuleName).collect(toList()); assertThat(packageSelectors).contains("java.base"); } @Test void packagesAreStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .selectors( selectPackage("org.junit.platform.engine") ).build(); // @formatter:on var packageSelectors = discoveryRequest.getSelectorsByType(PackageSelector.class).stream().map( PackageSelector::getPackageName).collect(toList()); assertThat(packageSelectors).contains("org.junit.platform.engine"); } @Test void classesAreStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .selectors( selectClass(LauncherDiscoveryRequestBuilderTests.class.getName()), selectClass(SampleTestClass.class) ) .build(); // @formatter:on List> classes = discoveryRequest.getSelectorsByType(ClassSelector.class).stream().map( ClassSelector::getJavaClass).collect(toList()); assertThat(classes).contains(SampleTestClass.class, LauncherDiscoveryRequestBuilderTests.class); } @Test void methodsByFullyQualifiedNameAreStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .selectors(selectMethod(fullyQualifiedMethodName())) .build(); // @formatter:on var methodSelectors = discoveryRequest.getSelectorsByType(MethodSelector.class); assertThat(methodSelectors).hasSize(1); var methodSelector = methodSelectors.get(0); assertThat(methodSelector.getJavaClass()).isEqualTo(LauncherDiscoveryRequestBuilderTests.class); assertThat(methodSelector.getJavaMethod()).isEqualTo(fullyQualifiedMethod()); } @Test void methodsByNameAreStoredInDiscoveryRequest() throws Exception { Class testClass = SampleTestClass.class; var testMethod = testClass.getDeclaredMethod("test"); // @formatter:off var discoveryRequest = request() .selectors(selectMethod(SampleTestClass.class.getName(), "test")) .build(); // @formatter:on var methodSelectors = discoveryRequest.getSelectorsByType(MethodSelector.class); assertThat(methodSelectors).hasSize(1); var methodSelector = methodSelectors.get(0); assertThat(methodSelector.getJavaClass()).isEqualTo(testClass); assertThat(methodSelector.getJavaMethod()).isEqualTo(testMethod); } @Test void methodsByClassAreStoredInDiscoveryRequest() throws Exception { Class testClass = SampleTestClass.class; var testMethod = testClass.getDeclaredMethod("test"); // @formatter:off var discoveryRequest = (DefaultDiscoveryRequest) request() .selectors( selectMethod(testClass, "test") ).build(); // @formatter:on var methodSelectors = discoveryRequest.getSelectorsByType(MethodSelector.class); assertThat(methodSelectors).hasSize(1); var methodSelector = methodSelectors.get(0); assertThat(methodSelector.getJavaClass()).isEqualTo(testClass); assertThat(methodSelector.getJavaMethod()).isEqualTo(testMethod); } @Test void uniqueIdsAreStoredInDiscoveryRequest() { var id1 = UniqueId.forEngine("engine").append("foo", "id1"); var id2 = UniqueId.forEngine("engine").append("foo", "id2"); // @formatter:off var discoveryRequest = request() .selectors( selectUniqueId(id1), selectUniqueId(id2) ).build(); // @formatter:on var uniqueIds = discoveryRequest.getSelectorsByType(UniqueIdSelector.class).stream().map( UniqueIdSelector::getUniqueId).map(Object::toString).collect(toList()); assertThat(uniqueIds).contains(id1.toString(), id2.toString()); } } @Nested class DiscoveryFilterTests { @Test void engineFiltersAreStoredInDiscoveryRequest() { TestEngine engine1 = new TestEngineStub("engine1"); TestEngine engine2 = new TestEngineStub("engine2"); TestEngine engine3 = new TestEngineStub("engine3"); // @formatter:off var discoveryRequest = request() .filters(includeEngines(engine1.getId(), engine2.getId())) .build(); // @formatter:on var filters = discoveryRequest.getEngineFilters(); assertThat(filters).hasSize(1); var engineFilter = filters.get(0); assertTrue(engineFilter.apply(engine1).included()); assertTrue(engineFilter.apply(engine2).included()); assertTrue(engineFilter.apply(engine3).excluded()); } @Test void discoveryFiltersAreStoredInDiscoveryRequest() { var filter1 = new DiscoveryFilterStub<>("filter1"); var filter2 = new DiscoveryFilterStub<>("filter2"); // @formatter:off var discoveryRequest = request() .filters(filter1, filter2) .build(); // @formatter:on var filters = discoveryRequest.getFiltersByType(DiscoveryFilter.class); assertThat(filters).containsOnly(filter1, filter2); } @Test void postDiscoveryFiltersAreStoredInDiscoveryRequest() { var postFilter1 = new PostDiscoveryFilterStub("postFilter1"); var postFilter2 = new PostDiscoveryFilterStub("postFilter2"); // @formatter:off var discoveryRequest = request() .filters(postFilter1, postFilter2) .build(); // @formatter:on var filters = discoveryRequest.getPostDiscoveryFilters(); assertThat(filters).containsOnly(postFilter1, postFilter2); } @Test void exceptionForIllegalFilterClass() { Exception exception = assertThrows(PreconditionViolationException.class, () -> request().filters(o -> excluded("reason"))); assertThat(exception).hasMessageStartingWith("Filter"); assertThat(exception).hasMessageEndingWith( "must implement EngineFilter, PostDiscoveryFilter, or DiscoveryFilter."); } } @Nested class DiscoveryConfigurationParameterTests { @Test void withoutConfigurationParametersSet_NoConfigurationParametersAreStoredInDiscoveryRequest() { var discoveryRequest = request().build(); var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key")).isNotPresent(); } @Test void configurationParameterAddedDirectly_isStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .configurationParameter("key", "value") .build(); // @formatter:on var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key")).contains("value"); } @Test void configurationParameterAddedDirectlyTwice_overridesPreviousValueInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .configurationParameter("key", "value") .configurationParameter("key", "value-new") .build(); // @formatter:on var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key")).contains("value-new"); } @Test void multipleConfigurationParametersAddedDirectly_areStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .configurationParameter("key1", "value1") .configurationParameter("key2", "value2") .build(); // @formatter:on var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key1")).contains("value1"); assertThat(configParams.get("key2")).contains("value2"); } @Test void configurationParameterAddedByMap_isStoredInDiscoveryRequest() { // @formatter:off var discoveryRequest = request() .configurationParameters(Map.of("key", "value")) .build(); // @formatter:on var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key")).contains("value"); } @Test void multipleConfigurationParametersAddedByMap_areStoredInDiscoveryRequest() { Map configurationParams = new HashMap<>(); configurationParams.put("key1", "value1"); configurationParams.put("key2", "value2"); // @formatter:off var discoveryRequest = request() .configurationParameters(configurationParams) .build(); // @formatter:on var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key1")).contains("value1"); assertThat(configParams.get("key2")).contains("value2"); } } @Nested class DiscoveryListenerTests { @Test void usesAbortOnFailureByDefault() { var request = request().build(); assertThat(request.getDiscoveryListener()).isEqualTo(abortOnFailure()); } @Test void onlyAddsAbortOnFailureOnce() { var request = request() // .listeners(abortOnFailure()) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "abortOnFailure") // .build(); assertThat(request.getDiscoveryListener()).isEqualTo(abortOnFailure()); } @Test void onlyAddsLoggingOnce() { var request = request() // .listeners(logging()) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .build(); assertThat(request.getDiscoveryListener()).isEqualTo(logging()); } @Test void createsCompositeForMultipleListeners() { var request = request() // .listeners(logging(), abortOnFailure()) // .build(); assertThat(request.getDiscoveryListener().getClass().getSimpleName()).startsWith("Composite"); } } private static class SampleTestClass { @Test void test() { } } private static String fullyQualifiedMethodName() { return LauncherDiscoveryRequestBuilderTests.class.getName() + "#" + fullyQualifiedMethod().getName(); } private static Method fullyQualifiedMethod() { try { return LauncherDiscoveryRequestBuilderTests.class.getDeclaredMethod("myTest"); } catch (Exception ex) { throw new IllegalStateException(ex); } } void myTest() { } } LauncherFactoryTests.java000066400000000000000000000313211455764576500340770ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.LauncherConstants.DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; import java.net.URLClassLoader; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestEngineSpy; import org.junit.platform.launcher.InterceptedTestEngine; import org.junit.platform.launcher.InterceptorInjectedLauncherSessionListener; import org.junit.platform.launcher.LauncherConstants; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TagFilter; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestLauncherDiscoveryListener; import org.junit.platform.launcher.TestLauncherInterceptor1; import org.junit.platform.launcher.TestLauncherInterceptor2; import org.junit.platform.launcher.TestLauncherSessionListener; import org.junit.platform.launcher.listeners.AnotherUnusedTestExecutionListener; import org.junit.platform.launcher.listeners.NoopTestExecutionListener; import org.junit.platform.launcher.listeners.UnusedTestExecutionListener; /** * @since 1.0 */ class LauncherFactoryTests { @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> LauncherFactory.create(null)); } @Test void testExecutionListenerIsLoadedViaServiceApi() { withTestServices(() -> { var config = LauncherConfig.builder() // .addTestEngines(new TestEngineSpy()) // .enableTestEngineAutoRegistration(false) // .build(); var launcher = LauncherFactory.create(config); NoopTestExecutionListener.called = false; launcher.execute(request().build()); assertTrue(NoopTestExecutionListener.called); }); } @Test void testExecutionListenersExcludedViaConfigParametersIsNotLoadedViaServiceApi() { withTestServices(() -> { var value = "org.junit.*.launcher.listeners.Unused*,org.junit.*.launcher.listeners.AnotherUnused*"; withSystemProperty(DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME, value, () -> { var config = LauncherConfig.builder() // .addTestEngines(new TestEngineSpy()) // .enableTestEngineAutoRegistration(false) // .build(); var launcher = LauncherFactory.create(config); UnusedTestExecutionListener.called = false; AnotherUnusedTestExecutionListener.called = false; launcher.execute(request().build()); assertFalse(UnusedTestExecutionListener.called); assertFalse(AnotherUnusedTestExecutionListener.called); }); }); } @Test void create() { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var testPlan = LauncherFactory.create().discover(discoveryRequest); var roots = testPlan.getRoots(); assertThat(roots).hasSize(3); // @formatter:off var ids = roots.stream() .map(TestIdentifier::getUniqueId) .collect(toList()); // @formatter:on assertThat(ids).containsOnly("[engine:junit-vintage]", "[engine:junit-jupiter]", "[engine:junit-platform-suite]"); } @Test void createWithConfig() { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// .enableTestEngineAutoRegistration(false)// .addTestEngines(new JupiterTestEngine())// .build(); var testPlan = LauncherFactory.create(config).discover(discoveryRequest); var roots = testPlan.getRoots(); assertThat(roots).hasSize(1); // @formatter:off var ids = roots.stream() .map(TestIdentifier::getUniqueId) .collect(toList()); // @formatter:on assertThat(ids).containsOnly("[engine:junit-jupiter]"); } @Test void createWithPostDiscoveryFilters() { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// .addPostDiscoveryFilters(TagFilter.includeTags("test-post-discovery")).build(); var testPlan = LauncherFactory.create(config).discover(discoveryRequest); final var vintage = testPlan.getChildren(UniqueId.parse("[engine:junit-vintage]")); assertThat(vintage).isEmpty(); final var jupiter = testPlan.getChildren(UniqueId.parse("[engine:junit-jupiter]")); assertThat(jupiter).hasSize(1); } @Test void applyPostDiscoveryFiltersViaServiceApi() { withTestServices(() -> { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// .build(); var testPlan = LauncherFactory.create(config).discover(discoveryRequest); final var vintage = testPlan.getChildren(UniqueId.parse("[engine:junit-vintage]")); assertThat(vintage).isEmpty(); final var jupiter = testPlan.getChildren(UniqueId.parse("[engine:junit-jupiter]")); assertThat(jupiter).hasSize(1); }); } @Test void notApplyIfDisabledPostDiscoveryFiltersViaServiceApi() { withTestServices(() -> { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// .enablePostDiscoveryFilterAutoRegistration(false).build(); var testPlan = LauncherFactory.create(config).discover(discoveryRequest); final var vintage = testPlan.getChildren(UniqueId.parse("[engine:junit-vintage]")); assertThat(vintage).hasSize(1); final var jupiter = testPlan.getChildren(UniqueId.parse("[engine:junit-jupiter]")); assertThat(jupiter).hasSize(1); }); } @Test void doesNotDiscoverLauncherDiscoverRequestListenerViaServiceApiWhenDisabled() { withTestServices(() -> { var config = LauncherConfig.builder() // .enableLauncherDiscoveryListenerAutoRegistration(false) // .build(); var launcher = LauncherFactory.create(config); TestLauncherDiscoveryListener.called = false; launcher.discover(request().build()); assertFalse(TestLauncherDiscoveryListener.called); }); } @Test void discoversLauncherDiscoverRequestListenerViaServiceApiByDefault() { withTestServices(() -> { var launcher = LauncherFactory.create(); TestLauncherDiscoveryListener.called = false; launcher.discover(request().build()); assertTrue(TestLauncherDiscoveryListener.called); }); } @Test void doesNotDiscoverLauncherSessionListenerViaServiceApiWhenDisabled() { withTestServices(() -> { try (var session = (DefaultLauncherSession) LauncherFactory.openSession( LauncherConfig.builder().enableLauncherSessionListenerAutoRegistration(false).build())) { assertThat(session.getListener()).isSameAs(LauncherSessionListener.NOOP); } }); } @Test void discoversLauncherSessionListenerViaServiceApiByDefault() { withTestServices(() -> { try (var session = (DefaultLauncherSession) LauncherFactory.openSession()) { assertThat(session.getListener()).isEqualTo(new TestLauncherSessionListener()); } }); } @Test void createsLauncherInterceptorsBeforeDiscoveringTestEngines() { withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { var config = LauncherConfig.builder() // .enableTestEngineAutoRegistration(true) // .build(); var request = request().build(); var testPlan = LauncherFactory.create(config).discover(request); assertThat(testPlan.getRoots()) // .map(TestIdentifier::getUniqueIdObject) // .map(UniqueId::getLastSegment) // .map(UniqueId.Segment::getValue) // .describedAs( "Intercepted test engine is added by class loader created by TestLauncherInterceptor1").contains( InterceptedTestEngine.ID); })); } @Test void appliesLauncherInterceptorsToTestDiscovery() { InterceptorInjectedLauncherSessionListener.CALLS = 0; withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { var engine = new TestEngineSpy() { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { throw new RuntimeException("from discovery"); } }; var config = LauncherConfig.builder() // .enableTestEngineAutoRegistration(false) // .addTestEngines(engine) // .build(); var launcher = LauncherFactory.create(config); var request = request().build(); var exception = assertThrows(RuntimeException.class, () -> launcher.discover(request)); assertThat(exception) // .hasRootCauseMessage("from discovery") // .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); assertThat(InterceptorInjectedLauncherSessionListener.CALLS).isEqualTo(1); })); } @Test void appliesLauncherInterceptorsToTestExecution() { InterceptorInjectedLauncherSessionListener.CALLS = 0; withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { var engine = new TestEngineSpy() { @Override public void execute(ExecutionRequest request) { throw new RuntimeException("from execution"); } }; var config = LauncherConfig.builder() // .enableTestEngineAutoRegistration(false) // .addTestEngines(engine) // .build(); var launcher = LauncherFactory.create(config); var request = request().configurationParameter(LauncherConstants.STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME, "false").build(); AtomicReference result = new AtomicReference<>(); launcher.execute(request, new TestExecutionListener() { @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { if (testIdentifier.getParentId().isEmpty()) { result.set(testExecutionResult); } } }); assertThat(result.get().getThrowable().orElseThrow()) // .hasRootCauseMessage("from execution") // .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); assertThat(InterceptorInjectedLauncherSessionListener.CALLS).isEqualTo(1); })); } @SuppressWarnings("SameParameterValue") private static void withSystemProperty(String key, String value, Runnable runnable) { var oldValue = System.getProperty(key); System.setProperty(key, value); try { runnable.run(); } finally { if (oldValue == null) { System.clearProperty(key); } else { System.setProperty(key, oldValue); } } } private static void withTestServices(Runnable runnable) { var current = Thread.currentThread().getContextClassLoader(); var url = LauncherFactoryTests.class.getClassLoader().getResource("testservices/"); try (var classLoader = new URLClassLoader(new URL[] { url }, current)) { Thread.currentThread().setContextClassLoader(classLoader); runnable.run(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { Thread.currentThread().setContextClassLoader(current); } } private LauncherDiscoveryRequest createLauncherDiscoveryRequestForBothStandardEngineExampleClasses() { // @formatter:off return request() .selectors(selectClass(JUnit4Example.class)) .selectors(selectClass(JUnit5Example.class)) .build(); // @formatter:on } @SuppressWarnings("NewClassNamingConvention") public static class JUnit4Example { @org.junit.Test public void testJ4() { } } @SuppressWarnings("NewClassNamingConvention") static class JUnit5Example { @Tag("test-post-discovery") @Test void testJ5() { } } } LauncherSessionTests.java000066400000000000000000000110671455764576500341200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncherConfigBuilderWithDisabledServiceLoading; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.fakes.TestEngineStub; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.mockito.ArgumentCaptor; class LauncherSessionTests { LauncherSessionListener firstSessionListener = mock(LauncherSessionListener.class, "firstSessionListener"); LauncherSessionListener secondSessionListener = mock(LauncherSessionListener.class, "secondSessionListener"); LauncherConfig launcherConfig = createLauncherConfigBuilderWithDisabledServiceLoading() // .addLauncherSessionListeners(firstSessionListener, secondSessionListener) // .addTestEngines(new TestEngineStub()) // .build(); LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request().build(); @Test void callsRegisteredListenersWhenLauncherIsUsedDirectly() { var launcher = LauncherFactory.create(launcherConfig); var testPlan = launcher.discover(request); var inOrder = inOrder(firstSessionListener, secondSessionListener); var launcherSession = ArgumentCaptor.forClass(LauncherSession.class); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); launcher.execute(testPlan); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); launcher.execute(request); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); } @Test void callsRegisteredListenersWhenLauncherIsUsedViaSession() { @SuppressWarnings("resource") var session = LauncherFactory.openSession(launcherConfig); var launcher = session.getLauncher(); var inOrder = inOrder(firstSessionListener, secondSessionListener); inOrder.verify(firstSessionListener).launcherSessionOpened(session); inOrder.verify(secondSessionListener).launcherSessionOpened(session); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); var testPlan = launcher.discover(request); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); launcher.execute(testPlan); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); launcher.execute(request); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); session.close(); inOrder.verify(secondSessionListener).launcherSessionClosed(session); inOrder.verify(firstSessionListener).launcherSessionClosed(session); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); } @Test void closedSessionCannotBeUsed() { @SuppressWarnings("resource") var session = LauncherFactory.openSession(launcherConfig); var launcher = session.getLauncher(); var testPlan = launcher.discover(request); session.close(); assertThrows(PreconditionViolationException.class, () -> launcher.discover(request)); assertThrows(PreconditionViolationException.class, () -> launcher.execute(testPlan)); assertThrows(PreconditionViolationException.class, () -> launcher.execute(request)); } } ListenerRegistryTests.java000066400000000000000000000027721455764576500343340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; public class ListenerRegistryTests { @Test void registerWithNullArray() { var registry = ListenerRegistry.create(l -> l.get(0)); var exception = assertThrows(PreconditionViolationException.class, () -> registry.addAll((Object[]) null)); assertThat(exception).hasMessageContaining("listeners array must not be null or empty"); } @Test void registerWithEmptyArray() { var registry = ListenerRegistry.create(l -> l.get(0)); var exception = assertThrows(PreconditionViolationException.class, registry::addAll); assertThat(exception).hasMessageContaining("listeners array must not be null or empty"); } @Test void registerWithArrayContainingNullElements() { var registry = ListenerRegistry.create(l -> l.get(0)); var exception = assertThrows(PreconditionViolationException.class, () -> registry.addAll(new Object[] { null })); assertThat(exception).hasMessageContaining("individual listeners must not be null"); } } StreamInterceptingTestExecutionListenerIntegrationTests.java000066400000000000000000000147421455764576500432630ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.LauncherConstants.STDOUT_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.function.Supplier; import java.util.stream.Stream; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.junit.platform.launcher.LauncherConstants; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.mockito.ArgumentCaptor; /** * @since 1.3 */ class StreamInterceptingTestExecutionListenerIntegrationTests { @ParameterizedTest(name = "{0}") @MethodSource("systemStreams") @ExtendWith(HiddenSystemOutAndErr.class) void interceptsStream(String configParam, Supplier printStreamSupplier, String reportKey) { var engine = new DemoHierarchicalTestEngine("engine"); TestDescriptor test = engine.addTest("test", () -> printStreamSupplier.get().print("4567890")); var listener = mock(TestExecutionListener.class); doAnswer(invocation -> { TestIdentifier testIdentifier = invocation.getArgument(0); if (testIdentifier.getUniqueIdObject().equals(test.getUniqueId())) { printStreamSupplier.get().print("123"); } return null; }).when(listener).executionStarted(any()); var launcher = createLauncher(engine); var discoveryRequest = request()// .selectors(selectUniqueId(test.getUniqueId()))// .configurationParameter(configParam, String.valueOf(true))// .configurationParameter(LauncherConstants.CAPTURE_MAX_BUFFER_PROPERTY_NAME, String.valueOf(5))// .build(); launcher.execute(discoveryRequest, listener); var testPlanArgumentCaptor = ArgumentCaptor.forClass(TestPlan.class); var inOrder = inOrder(listener); inOrder.verify(listener).testPlanExecutionStarted(testPlanArgumentCaptor.capture()); var testPlan = testPlanArgumentCaptor.getValue(); var testIdentifier = testPlan.getTestIdentifier(test.getUniqueId()); var reportEntryArgumentCaptor = ArgumentCaptor.forClass(ReportEntry.class); inOrder.verify(listener).reportingEntryPublished(same(testIdentifier), reportEntryArgumentCaptor.capture()); inOrder.verify(listener).executionFinished(testIdentifier, successful()); var reportEntry = reportEntryArgumentCaptor.getValue(); assertThat(reportEntry.getKeyValuePairs()).containsExactly(entry(reportKey, "12345")); } @ParameterizedTest(name = "{0}") @MethodSource("systemStreams") @ExtendWith(HiddenSystemOutAndErr.class) void doesNotInterceptStreamWhenAlreadyBeingIntercepted(String configParam, Supplier printStreamSupplier) { var engine = new DemoHierarchicalTestEngine("engine"); TestDescriptor test = engine.addTest("test", () -> printStreamSupplier.get().print("1234567890")); assertThat(StreamInterceptor.registerStdout(1)).isPresent(); assertThat(StreamInterceptor.registerStderr(1)).isPresent(); var launcher = createLauncher(engine); var discoveryRequest = request()// .selectors(selectUniqueId(test.getUniqueId()))// .configurationParameter(configParam, String.valueOf(true))// .build(); var listener = mock(TestExecutionListener.class); launcher.execute(discoveryRequest, listener); verify(listener, never()).reportingEntryPublished(any(), any()); } @SuppressWarnings("unused") // used via @MethodSource("systemStreams") private static Stream systemStreams() { return Stream.of(// streamType(CAPTURE_STDOUT_PROPERTY_NAME, () -> System.out, STDOUT_REPORT_ENTRY_KEY), // streamType(CAPTURE_STDERR_PROPERTY_NAME, () -> System.err, STDERR_REPORT_ENTRY_KEY)); } private static Arguments streamType(String configParam, Supplier printStreamSupplier, String reportKey) { return arguments(configParam, printStreamSupplier, reportKey); } static class HiddenSystemOutAndErr implements BeforeTestExecutionCallback, AfterTestExecutionCallback { private static final Namespace NAMESPACE = Namespace.create(HiddenSystemOutAndErr.class); @Override public void beforeTestExecution(ExtensionContext context) { var store = context.getStore(NAMESPACE); store.put("out", System.out); store.put("err", System.err); System.setOut(new PrintStream(new ByteArrayOutputStream())); System.setErr(new PrintStream(new ByteArrayOutputStream())); } @Override public void afterTestExecution(ExtensionContext context) { var store = context.getStore(NAMESPACE); System.setOut(store.get("out", PrintStream.class)); System.setErr(store.get("err", PrintStream.class)); } } } StreamInterceptorTests.java000066400000000000000000000062321455764576500344630ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/core/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.core; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; /** * @since 1.3 */ class StreamInterceptorTests { private ByteArrayOutputStream originalOut = new ByteArrayOutputStream(); private PrintStream targetStream = new PrintStream(originalOut); @Test void interceptsWriteOperationsToStreamPerThread() { var streamInterceptor = StreamInterceptor.register(targetStream, newStream -> this.targetStream = newStream, 3).orElseThrow(RuntimeException::new); // @formatter:off IntStream.range(0, 1000) .parallel() .peek(i -> targetStream.println(i)) .mapToObj(String::valueOf) .peek(i -> streamInterceptor.capture()) .peek(i -> targetStream.println(i)) .forEach(i -> assertEquals(i, streamInterceptor.consume().trim())); // @formatter:on } @Test void unregisterRestoresOriginalStream() { var originalStream = targetStream; var streamInterceptor = StreamInterceptor.register(targetStream, newStream -> this.targetStream = newStream, 3).orElseThrow(RuntimeException::new); assertSame(streamInterceptor, targetStream); streamInterceptor.unregister(); assertSame(originalStream, targetStream); } @Test void writeForwardsOperationsToOriginalStream() throws IOException { var originalStream = targetStream; StreamInterceptor.register(targetStream, newStream -> this.targetStream = newStream, 2).orElseThrow( RuntimeException::new); assertNotSame(originalStream, targetStream); targetStream.write('a'); targetStream.write("b".getBytes()); targetStream.write("c".getBytes(), 0, 1); assertEquals("abc", originalOut.toString()); } @Test void handlesNestedCaptures() { var streamInterceptor = StreamInterceptor.register(targetStream, newStream -> this.targetStream = newStream, 100).orElseThrow(RuntimeException::new); String outermost, inner, innermost; streamInterceptor.capture(); streamInterceptor.print("before outermost - "); { streamInterceptor.capture(); streamInterceptor.print("before inner - "); { streamInterceptor.capture(); streamInterceptor.print("innermost"); innermost = streamInterceptor.consume(); } streamInterceptor.print("after inner"); inner = streamInterceptor.consume(); } streamInterceptor.print("after outermost"); outermost = streamInterceptor.consume(); assertAll(// () -> assertEquals("before outermost - after outermost", outermost), // () -> assertEquals("before inner - after inner", inner), // () -> assertEquals("innermost", innermost) // ); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/000077500000000000000000000000001455764576500302575ustar00rootroot00000000000000AnotherUnusedTestExecutionListener.java000066400000000000000000000012421455764576500400600ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; public class AnotherUnusedTestExecutionListener implements TestExecutionListener { public static boolean called; @Override public void testPlanExecutionStarted(TestPlan testPlan) { called = true; } } NoopTestExecutionListener.java000066400000000000000000000012571455764576500362150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ public class NoopTestExecutionListener implements TestExecutionListener { public static boolean called; @Override public void testPlanExecutionStarted(TestPlan testPlan) { called = true; } } OutputDirTests.java000066400000000000000000000051261455764576500340310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import org.junit.jupiter.api.Test; class OutputDirTests { @Test void getOutputDirUsesCustomOutputDir() throws Exception { String customDir = "build/UniqueIdTrackingListenerIntegrationTests"; Path outputDir = OutputDir.create(Optional.of(customDir)).toPath(); assertThat(Files.isSameFile(Paths.get(customDir), outputDir)).isTrue(); assertThat(outputDir).exists(); } @Test void getOutputDirFallsBackToCurrentWorkingDir() throws Exception { String cwd = "src/test/resources/listeners/uidtracking"; String expected = cwd; assertOutputDirIsDetected(cwd, expected); } @Test void getOutputDirDetectsMavenPom() throws Exception { String cwd = "src/test/resources/listeners/uidtracking/maven"; String expected = cwd + "/target"; assertOutputDirIsDetected(cwd, expected); } @Test void getOutputDirDetectsGradleGroovyDefaultBuildScript() throws Exception { String cwd = "src/test/resources/listeners/uidtracking/gradle/groovy"; String expected = cwd + "/build"; assertOutputDirIsDetected(cwd, expected); } @Test void getOutputDirDetectsGradleGroovyCustomBuildScript() throws Exception { String cwd = "src/test/resources/listeners/uidtracking/gradle/groovy/sub-project"; String expected = cwd + "/build"; assertOutputDirIsDetected(cwd, expected); } @Test void getOutputDirDetectsGradleKotlinDefaultBuildScript() throws Exception { String cwd = "src/test/resources/listeners/uidtracking/gradle/kotlin"; String expected = cwd + "/build"; assertOutputDirIsDetected(cwd, expected); } @Test void getOutputDirDetectsGradleKotlinCustomBuildScript() throws Exception { String cwd = "src/test/resources/listeners/uidtracking/gradle/kotlin/sub-project"; String expected = cwd + "/build"; assertOutputDirIsDetected(cwd, expected); } private void assertOutputDirIsDetected(String cwd, String expected) throws IOException { Path outputDir = OutputDir.createSafely(Optional.empty(), () -> Paths.get(cwd)).toPath(); assertThat(Files.isSameFile(Paths.get(expected), outputDir)).isTrue(); assertThat(outputDir).exists(); } } SummaryGenerationTests.java000066400000000000000000000262421455764576500355450ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.test.ConcurrencyTestingUtils.executeConcurrently; import static org.mockito.Mockito.mock; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class SummaryGenerationTests { private final SummaryGeneratingListener listener = new SummaryGeneratingListener(); private final TestPlan testPlan = TestPlan.from(List.of(), mock()); @Test void emptyReport() { listener.testPlanExecutionStarted(testPlan); listener.testPlanExecutionFinished(testPlan); assertEquals(0, listener.getSummary().getTestsFailedCount()); var summaryString = summaryAsString(); assertAll("summary", // () -> assertTrue(summaryString.contains("Test run finished after"), "test run"), // () -> assertTrue(summaryString.contains("0 containers found"), "containers found"), // () -> assertTrue(summaryString.contains("0 containers skipped"), "containers skipped"), // () -> assertTrue(summaryString.contains("0 containers started"), "containers started"), // () -> assertTrue(summaryString.contains("0 containers aborted"), "containers aborted"), // () -> assertTrue(summaryString.contains("0 containers successful"), "containers successful"), // () -> assertTrue(summaryString.contains("0 containers failed"), "containers failed"), // () -> assertTrue(summaryString.contains("0 tests found"), "tests found"), // () -> assertTrue(summaryString.contains("0 tests skipped"), "tests skipped"), // () -> assertTrue(summaryString.contains("0 tests started"), "tests started"), // () -> assertTrue(summaryString.contains("0 tests aborted"), "tests aborted"), // () -> assertTrue(summaryString.contains("0 tests successful"), "tests successful"), // () -> assertTrue(summaryString.contains("0 tests failed"), "tests failed") // ); assertEquals("", failuresAsString()); } @Test void reportingCorrectCounts() { var successfulContainer = createContainerIdentifier("c1"); var failedContainer = createContainerIdentifier("c2"); var abortedContainer = createContainerIdentifier("c3"); var skippedContainer = createContainerIdentifier("c4"); var successfulTest = createTestIdentifier("t1"); var failedTest = createTestIdentifier("t2"); var abortedTest = createTestIdentifier("t3"); var skippedTest = createTestIdentifier("t4"); listener.testPlanExecutionStarted(testPlan); listener.executionSkipped(skippedContainer, "skipped"); listener.executionSkipped(skippedTest, "skipped"); listener.executionStarted(successfulContainer); listener.executionFinished(successfulContainer, TestExecutionResult.successful()); listener.executionStarted(successfulTest); listener.executionFinished(successfulTest, TestExecutionResult.successful()); listener.executionStarted(failedContainer); listener.executionFinished(failedContainer, TestExecutionResult.failed(new RuntimeException("failed"))); listener.executionStarted(failedTest); listener.executionFinished(failedTest, TestExecutionResult.failed(new RuntimeException("failed"))); listener.executionStarted(abortedContainer); listener.executionFinished(abortedContainer, TestExecutionResult.aborted(new RuntimeException("aborted"))); listener.executionStarted(abortedTest); listener.executionFinished(abortedTest, TestExecutionResult.aborted(new RuntimeException("aborted"))); listener.testPlanExecutionFinished(testPlan); var summaryString = summaryAsString(); try { assertAll("summary", // () -> assertTrue(summaryString.contains("4 containers found"), "containers found"), // () -> assertTrue(summaryString.contains("1 containers skipped"), "containers skipped"), // () -> assertTrue(summaryString.contains("3 containers started"), "containers started"), // () -> assertTrue(summaryString.contains("1 containers aborted"), "containers aborted"), // () -> assertTrue(summaryString.contains("1 containers successful"), "containers successful"), // () -> assertTrue(summaryString.contains("1 containers failed"), "containers failed"), // () -> assertTrue(summaryString.contains("4 tests found"), "tests found"), // () -> assertTrue(summaryString.contains("1 tests skipped"), "tests skipped"), // () -> assertTrue(summaryString.contains("3 tests started"), "tests started"), // () -> assertTrue(summaryString.contains("1 tests aborted"), "tests aborted"), // () -> assertTrue(summaryString.contains("1 tests successful"), "tests successful"), // () -> assertTrue(summaryString.contains("1 tests failed"), "tests failed") // ); } catch (AssertionError error) { System.err.println(summaryString); throw error; } } @Test void canGetListOfFailures() { var failedException = new RuntimeException("Pow!"); var testDescriptor = new TestDescriptorStub(UniqueId.root("root", "1"), "failingTest") { @Override public Optional getSource() { return Optional.of(ClassSource.from(Object.class)); } }; var failingTest = TestIdentifier.from(testDescriptor); listener.testPlanExecutionStarted(testPlan); listener.executionStarted(failingTest); listener.executionFinished(failingTest, TestExecutionResult.failed(failedException)); listener.testPlanExecutionFinished(testPlan); final var failures = listener.getSummary().getFailures(); assertThat(failures).hasSize(1); assertThat(failures.get(0).getException()).isEqualTo(failedException); assertThat(failures.get(0).getTestIdentifier()).isEqualTo(failingTest); } @Test void reportingCorrectFailures() { var iaeCausedBy = new IllegalArgumentException("Illegal Argument Exception"); var failedException = new RuntimeException("Runtime Exception", iaeCausedBy); var npeSuppressed = new NullPointerException("Null Pointer Exception"); failedException.addSuppressed(npeSuppressed); var testDescriptor = new TestDescriptorStub(UniqueId.root("root", "2"), "failingTest") { @Override public Optional getSource() { return Optional.of(ClassSource.from(Object.class)); } }; var failed = TestIdentifier.from(testDescriptor); var aborted = TestIdentifier.from(new TestDescriptorStub(UniqueId.root("root", "3"), "abortedTest")); listener.testPlanExecutionStarted(testPlan); listener.executionStarted(failed); listener.executionFinished(failed, TestExecutionResult.failed(failedException)); listener.executionStarted(aborted); listener.executionFinished(aborted, TestExecutionResult.aborted(new RuntimeException("aborted"))); listener.testPlanExecutionFinished(testPlan); // An aborted test is not a failure assertEquals(1, listener.getSummary().getTestsFailedCount()); var failuresString = failuresAsString(); assertAll("failures", // () -> assertTrue(failuresString.contains("Failures (1)"), "test failures"), // () -> assertTrue(failuresString.contains(Object.class.getName()), "source"), // () -> assertTrue(failuresString.contains("failingTest"), "display name"), // () -> assertTrue(failuresString.contains("=> " + failedException), "main exception"), // () -> assertTrue(failuresString.contains("Caused by: " + iaeCausedBy), "Caused by exception"), // () -> assertTrue(failuresString.contains("Suppressed: " + npeSuppressed), "Suppressed exception") // ); } @Test public void reportingCircularFailure() { var iaeCausedBy = new IllegalArgumentException("Illegal Argument Exception"); var failedException = new RuntimeException("Runtime Exception", iaeCausedBy); var npeSuppressed = new NullPointerException("Null Pointer Exception"); failedException.addSuppressed(npeSuppressed); npeSuppressed.addSuppressed(iaeCausedBy); var testDescriptor = new TestDescriptorStub(UniqueId.root("root", "2"), "failingTest") { @Override public Optional getSource() { return Optional.of(ClassSource.from(Object.class)); } }; var failed = TestIdentifier.from(testDescriptor); listener.testPlanExecutionStarted(testPlan); listener.executionStarted(failed); listener.executionFinished(failed, TestExecutionResult.failed(failedException)); listener.testPlanExecutionFinished(testPlan); assertEquals(1, listener.getSummary().getTestsFailedCount()); var failuresString = failuresAsString(); assertAll("failures", // () -> assertTrue(failuresString.contains("Suppressed: " + npeSuppressed), "Suppressed exception"), // () -> assertTrue(failuresString.contains("Circular reference: " + iaeCausedBy), "Circular reference"), // () -> assertFalse(failuresString.contains("Caused by: "), "'Caused by: ' omitted because of Circular reference") // ); } @RepeatedTest(10) void reportingConcurrentlyFinishedTests() throws Exception { var numThreads = 250; var testIdentifier = TestIdentifier.from(new TestDescriptorStub(UniqueId.root("root", "2"), "failingTest") { @Override public Optional getSource() { return Optional.of(ClassSource.from(Object.class)); } }); var result = TestExecutionResult.failed(new RuntimeException()); listener.testPlanExecutionStarted(testPlan); executeConcurrently(numThreads, () -> { listener.executionStarted(testIdentifier); listener.executionFinished(testIdentifier, result); }); listener.testPlanExecutionFinished(testPlan); assertThat(listener.getSummary().getFailures()).hasSize(numThreads); } private TestIdentifier createTestIdentifier(String uniqueId) { var identifier = TestIdentifier.from(new TestDescriptorStub(UniqueId.root("test", uniqueId), uniqueId)); testPlan.addInternal(identifier); return identifier; } private TestIdentifier createContainerIdentifier(String uniqueId) { var identifier = TestIdentifier.from(new TestDescriptorStub(UniqueId.root("container", uniqueId), uniqueId) { @Override public Type getType() { return Type.CONTAINER; } }); testPlan.addInternal(identifier); return identifier; } private String summaryAsString() { var summaryWriter = new StringWriter(); listener.getSummary().printTo(new PrintWriter(summaryWriter)); return summaryWriter.toString(); } private String failuresAsString() { var failuresWriter = new StringWriter(); listener.getSummary().printFailuresTo(new PrintWriter(failuresWriter)); return failuresWriter.toString(); } } UniqueIdTrackingListenerIntegrationTests.java000066400000000000000000000316401455764576500412120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.listeners.UniqueIdTrackingListener.DEFAULT_OUTPUT_FILE_PREFIX; import static org.junit.platform.launcher.listeners.UniqueIdTrackingListener.LISTENER_ENABLED_PROPERTY_NAME; import static org.junit.platform.launcher.listeners.UniqueIdTrackingListener.OUTPUT_DIR_PROPERTY_NAME; import static org.junit.platform.launcher.listeners.UniqueIdTrackingListener.OUTPUT_FILE_PREFIX_PROPERTY_NAME; import static org.junit.platform.testkit.engine.Event.byTestDescriptor; import static org.junit.platform.testkit.engine.EventConditions.abortedWithReason; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import java.util.stream.Stream; import org.assertj.core.api.Condition; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Event; import org.opentest4j.AssertionFailedError; import org.opentest4j.TestAbortedException; /** * Integration tests for the {@link UniqueIdTrackingListener}. * * @since 1.8 */ class UniqueIdTrackingListenerIntegrationTests { private static final String passingTest = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[method:passingTest()]"; private static final String skippedTest = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[method:skippedTest()]"; private static final String abortedTest = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[method:abortedTest()]"; private static final String failingTest = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[method:failingTest()]"; private static final String dynamicTest1 = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[test-factory:dynamicTests()]/[dynamic-test:#1]"; private static final String dynamicTest2 = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase1]/[test-factory:dynamicTests()]/[dynamic-test:#2]"; private static final String testA = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase2]/[method:testA()]"; private static final String testB = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase2]/[method:testB()]"; private static final String testC = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase3]/[method:testC()]"; private static final String testD = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase3]/[method:testD()]"; private static final String testE = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase4]/[method:testE()]"; private static final String testF = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase4]/[method:testF()]"; private static final String[] expectedUniqueIds = { passingTest, skippedTest, abortedTest, failingTest, dynamicTest1, dynamicTest2, testA, testB }; private static final String[] expectedConcurrentUniqueIds = { testA, testB, testC, testD, testE, testF }; @Test void confirmExpectedUniqueIdsViaEngineTestKit() { // @formatter:off EngineTestKit.engine("junit-jupiter") .selectors(selectClasses()) .execute() .testEvents() .assertStatistics(stats -> stats.started(7).skipped(1).aborted(1).succeeded(5).failed(1)) .assertEventsMatchLoosely( event(test(uniqueId(passingTest)), finishedSuccessfully()), event(test(uniqueId(abortedTest)), abortedWithReason(instanceOf(TestAbortedException.class))), event(test(uniqueId(failingTest)), finishedWithFailure(instanceOf(AssertionFailedError.class))), event(test(uniqueId(dynamicTest1)), finishedSuccessfully()), event(test(uniqueId(dynamicTest2)), finishedSuccessfully()), event(test(uniqueId(testA)), finishedSuccessfully()), event(test(uniqueId(testB)), finishedSuccessfully()) ); // @formatter:on } private Condition uniqueId(String uniqueId) { return new Condition<>( byTestDescriptor(where(TestDescriptor::getUniqueId, uid -> uid.toString().equals(uniqueId))), "descriptor with uniqueId '%s'", uniqueId); } @Test void listenerIsRegisteredButDisabledByDefault() throws Exception { long numListenersRegistered = ServiceLoader.load(TestExecutionListener.class).stream()// .filter(provider -> UniqueIdTrackingListener.class.equals(provider.type()))// .count(); assertThat(numListenersRegistered).isEqualTo(1); String outputDir = "build"; String prefix = DEFAULT_OUTPUT_FILE_PREFIX; deleteFiles(outputDir, prefix); try { List actualUniqueIds = executeTests(Map.of()); // Sanity check using the results of our local TestExecutionListener assertThat(actualUniqueIds).containsExactlyInAnyOrder(expectedUniqueIds); // Check that files were not generated by the UniqueIdTrackingListener assertThat(findFiles(outputDir, prefix)).isEmpty(); } finally { deleteFiles(outputDir, prefix); } } @Test void verifyUniqueIdsAreTrackedWithDefaults() throws Exception { verifyUniqueIdsAreTracked("build", DEFAULT_OUTPUT_FILE_PREFIX, Map.of()); } @Test void verifyUniqueIdsAreTrackedWithCustomOutputFile() throws Exception { String customPrefix = "test_ids"; verifyUniqueIdsAreTracked("build", customPrefix, Map.of(OUTPUT_FILE_PREFIX_PROPERTY_NAME, customPrefix)); } @Test void verifyUniqueIdsAreTrackedWithCustomOutputDir() throws Exception { String customDir = "build/UniqueIdTrackingListenerIntegrationTests"; verifyUniqueIdsAreTracked(customDir, DEFAULT_OUTPUT_FILE_PREFIX, Map.of(OUTPUT_DIR_PROPERTY_NAME, customDir)); } @Test void verifyUniqueIdsAreTrackedWithCustomOutputFileAndCustomOutputDir() throws Exception { String customPrefix = "test_ids"; String customDir = "build/UniqueIdTrackingListenerIntegrationTests"; verifyUniqueIdsAreTracked(customDir, customPrefix, Map.of(OUTPUT_DIR_PROPERTY_NAME, customDir, OUTPUT_FILE_PREFIX_PROPERTY_NAME, customPrefix)); } private void verifyUniqueIdsAreTracked(String outputDir, String prefix, Map configurationParameters) throws IOException { configurationParameters = new HashMap<>(configurationParameters); configurationParameters.put(LISTENER_ENABLED_PROPERTY_NAME, "true"); deleteFiles(outputDir, prefix); try { List actualUniqueIds = executeTests(configurationParameters); // Sanity check using the results of our local TestExecutionListener assertThat(actualUniqueIds).containsExactlyInAnyOrder(expectedUniqueIds); // Check contents of the file (or files) generated by the UniqueIdTrackingListener assertThat(readAllFiles(outputDir, prefix)).containsExactlyInAnyOrder(expectedUniqueIds); } finally { deleteFiles(outputDir, prefix); } } @Test void verifyUniqueIdsAreTrackedWithConcurrentlyExecutingTestPlans() throws Exception { String customDir = "build/UniqueIdTrackingListenerIntegrationTests"; String prefix = DEFAULT_OUTPUT_FILE_PREFIX; Map configurationParameters = new HashMap<>(); configurationParameters.put(LISTENER_ENABLED_PROPERTY_NAME, "true"); configurationParameters.put(OUTPUT_DIR_PROPERTY_NAME, customDir); deleteFiles(customDir, prefix); try { Stream.of(TestCase2.class, TestCase3.class, TestCase4.class).parallel()// .forEach(clazz -> executeTests(configurationParameters, selectClass(clazz))); // 3 output files should have been generated. assertThat(findFiles(customDir, prefix)).hasSize(3); // Check contents of the file (or files) generated by the UniqueIdTrackingListener assertThat(readAllFiles(customDir, prefix)).containsExactlyInAnyOrder(expectedConcurrentUniqueIds); } finally { deleteFiles(customDir, prefix); } } private static List executeTests(Map configurationParameters) { return executeTests(configurationParameters, selectClasses()); } private static List executeTests(Map configurationParameters, ClassSelector... classSelectors) { List uniqueIds = new ArrayList<>(); LauncherDiscoveryRequest request = request()// .selectors(classSelectors)// .filters(includeEngines("junit-jupiter"))// .configurationParameters(configurationParameters)// .build(); LauncherFactory.create().execute(request, new TestExecutionListener() { @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { if (testIdentifier.isTest()) { uniqueIds.add(testIdentifier.getUniqueId()); } } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { if (testIdentifier.isTest()) { uniqueIds.add(testIdentifier.getUniqueId()); } } }); return uniqueIds; } private static ClassSelector[] selectClasses() { return new ClassSelector[] { selectClass(TestCase1.class), selectClass(TestCase2.class) }; } private static Stream findFiles(String dir, String prefix) throws IOException { Path outputDir = Paths.get(dir); if (!Files.exists(outputDir)) { return Stream.empty(); } return Files.find(outputDir, 1, // (path, basicFileAttributes) -> (basicFileAttributes.isRegularFile() && path.getFileName().toString().startsWith(prefix))); } private void deleteFiles(String outputDir, String prefix) throws IOException { findFiles(outputDir, prefix).forEach(file -> { try { Files.deleteIfExists(file); } catch (IOException ex) { throw new UncheckedIOException(ex); } }); } private Stream readAllFiles(String outputDir, String prefix) throws IOException { return findFiles(outputDir, prefix).map(outputFile -> { try { return Files.readAllLines(outputFile); } catch (IOException ex) { throw new UncheckedIOException(ex); } }).flatMap(List::stream); } // ------------------------------------------------------------------------- static class TestCase1 { @Test void passingTest() { } @Test @Disabled("testing") void skippedTest() { } @Test void abortedTest() { assumeTrue(false); } @Test void failingTest() { fail(); } @TestFactory Stream dynamicTests() { return Stream.of("cat", "dog").map(text -> dynamicTest(text, () -> assertEquals(3, text.length()))); } } static class TestCase2 { @Test void testA() { } @Test void testB() { } } static class TestCase3 { @Test void testC() { } @Test void testD() { } } static class TestCase4 { @Test void testE() { } @Test void testF() { } } } UnusedTestExecutionListener.java000066400000000000000000000012331455764576500365370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestPlan; public class UnusedTestExecutionListener implements TestExecutionListener { public static boolean called; @Override public void testPlanExecutionStarted(TestPlan testPlan) { called = true; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/discovery/000077500000000000000000000000001455764576500322665ustar00rootroot00000000000000AbortOnFailureLauncherDiscoveryListenerTests.java000066400000000000000000000074071455764576500440410ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners.abortOnFailure; import org.junit.jupiter.api.Test; import org.junit.platform.commons.JUnitException; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestEngineStub; class AbortOnFailureLauncherDiscoveryListenerTests extends AbstractLauncherDiscoveryListenerTests { @Test void abortsDiscoveryOnUnresolvedUniqueIdSelectorWithEnginePrefix() { var engine = createEngineThatCannotResolveAnything("some-engine"); var request = request() // .listeners(abortOnFailure()) // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .build(); var launcher = createLauncher(engine); var exception = assertThrows(JUnitException.class, () -> launcher.discover(request)); assertThat(exception).hasMessage("TestEngine with ID 'some-engine' failed to discover tests"); assertThat(exception.getCause()).hasMessage( "UniqueIdSelector [uniqueId = [engine:some-engine]] could not be resolved"); } @Test void doesNotAbortDiscoveryOnUnresolvedUniqueIdSelectorWithoutEnginePrefix() { var engine = createEngineThatCannotResolveAnything("some-engine"); var request = request() // .listeners(abortOnFailure()) // .selectors(selectUniqueId(UniqueId.forEngine("some-other-engine"))) // .build(); var launcher = createLauncher(engine); assertDoesNotThrow(() -> launcher.discover(request)); } @Test void abortsDiscoveryOnSelectorResolutionFailure() { var rootCause = new RuntimeException(); var engine = createEngineThatFailsToResolveAnything("some-engine", rootCause); var request = request() // .listeners(abortOnFailure()) // .selectors(selectClass(Object.class)) // .build(); var launcher = createLauncher(engine); var exception = assertThrows(JUnitException.class, () -> launcher.discover(request)); assertThat(exception).hasMessage("TestEngine with ID 'some-engine' failed to discover tests"); assertThat(exception.getCause()) // .hasMessageEndingWith("resolution failed") // .hasCauseReference(rootCause); } @Test void abortsDiscoveryOnEngineDiscoveryFailure() { var rootCause = new RuntimeException(); var engine = new TestEngineStub("some-engine") { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { throw rootCause; } }; var request = request() // .listeners(abortOnFailure()) // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .build(); var launcher = createLauncher(engine); var exception = assertThrows(JUnitException.class, () -> launcher.discover(request)); assertThat(exception) // .hasMessage("TestEngine with ID 'some-engine' failed to discover tests") // .hasCauseReference(rootCause); } } AbstractLauncherDiscoveryListenerTests.java000066400000000000000000000035471455764576500427310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestEngineStub; abstract class AbstractLauncherDiscoveryListenerTests { protected TestEngineStub createEngineThatCannotResolveAnything(String engineId) { return new TestEngineStub(engineId) { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { discoveryRequest.getSelectorsByType(DiscoverySelector.class) // .forEach(selector -> discoveryRequest.getDiscoveryListener().selectorProcessed(uniqueId, selector, SelectorResolutionResult.unresolved())); return new EngineDescriptor(uniqueId, "Some Engine"); } }; } protected TestEngineStub createEngineThatFailsToResolveAnything(String engineId, RuntimeException rootCause) { return new TestEngineStub(engineId) { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { discoveryRequest.getSelectorsByType(DiscoverySelector.class) // .forEach(selector -> discoveryRequest.getDiscoveryListener().selectorProcessed(uniqueId, selector, SelectorResolutionResult.failed(rootCause))); return new EngineDescriptor(uniqueId, "Some Engine"); } }; } } CompositeLauncherDiscoveryListenerTests.java000066400000000000000000000052401455764576500431200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.engine.SelectorResolutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.EngineDiscoveryResult; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.mockito.InOrder; class CompositeLauncherDiscoveryListenerTests { @Test void callsListenersInReverseOrderForFinishedEvents() { var firstListener = mock(LauncherDiscoveryListener.class, "firstListener"); var secondListener = mock(LauncherDiscoveryListener.class, "secondListener"); var launcherDiscoveryRequest = mock(LauncherDiscoveryRequest.class); var engineId = UniqueId.forEngine("engine"); var engineDiscoveryResult = EngineDiscoveryResult.successful(); var selector = selectUniqueId(engineId); var selectorResolutionResult = SelectorResolutionResult.resolved(); var composite = new CompositeLauncherDiscoveryListener(List.of(firstListener, secondListener)); composite.launcherDiscoveryStarted(launcherDiscoveryRequest); composite.engineDiscoveryStarted(engineId); composite.selectorProcessed(engineId, selector, selectorResolutionResult); composite.engineDiscoveryFinished(engineId, engineDiscoveryResult); composite.launcherDiscoveryFinished(launcherDiscoveryRequest); InOrder inOrder = inOrder(firstListener, secondListener); inOrder.verify(firstListener).launcherDiscoveryStarted(launcherDiscoveryRequest); inOrder.verify(secondListener).launcherDiscoveryStarted(launcherDiscoveryRequest); inOrder.verify(firstListener).engineDiscoveryStarted(engineId); inOrder.verify(secondListener).engineDiscoveryStarted(engineId); inOrder.verify(secondListener).selectorProcessed(engineId, selector, selectorResolutionResult); inOrder.verify(secondListener).engineDiscoveryFinished(engineId, engineDiscoveryResult); inOrder.verify(firstListener).engineDiscoveryFinished(engineId, engineDiscoveryResult); inOrder.verify(secondListener).launcherDiscoveryFinished(launcherDiscoveryRequest); inOrder.verify(firstListener).launcherDiscoveryFinished(launcherDiscoveryRequest); } } LoggingLauncherDiscoveryListenerTests.java000066400000000000000000000121621455764576500425450ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/discovery/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.discovery; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.platform.commons.logging.LogRecordListener; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestEngineStub; @TrackLogRecords public class LoggingLauncherDiscoveryListenerTests extends AbstractLauncherDiscoveryListenerTests { @Test void logsWarningOnUnresolvedUniqueIdSelectorWithEnginePrefix(LogRecordListener log) { var engine = createEngineThatCannotResolveAnything("some-engine"); var request = request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .build(); var launcher = createLauncher(engine); launcher.discover(request); assertThat(log.stream(LoggingLauncherDiscoveryListener.class, Level.WARNING)) // .extracting(LogRecord::getMessage) // .containsExactly( "UniqueIdSelector [uniqueId = [engine:some-engine]] could not be resolved by [engine:some-engine]"); } @Test void logsDebugMessageOnUnresolvedUniqueIdSelectorWithoutEnginePrefix(LogRecordListener log) { var engine = createEngineThatCannotResolveAnything("some-engine"); var request = request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .selectors(selectUniqueId(UniqueId.forEngine("some-other-engine"))) // .build(); var launcher = createLauncher(engine); launcher.discover(request); assertThat(log.stream(LoggingLauncherDiscoveryListener.class, Level.FINE)) // .extracting(LogRecord::getMessage) // .containsExactly( "UniqueIdSelector [uniqueId = [engine:some-other-engine]] could not be resolved by [engine:some-engine]"); } @Test void logsErrorOnSelectorResolutionFailure(LogRecordListener log) { var rootCause = new RuntimeException(); var engine = createEngineThatFailsToResolveAnything("some-engine", rootCause); var request = request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .selectors(selectClass(Object.class)) // .build(); var launcher = createLauncher(engine); launcher.discover(request); assertThat(log.stream(LoggingLauncherDiscoveryListener.class, Level.SEVERE)) // .extracting(LogRecord::getMessage) // .containsExactly( "Resolution of ClassSelector [className = 'java.lang.Object', classLoader = null] by [engine:some-engine] failed"); } @Test void logsErrorOnEngineDiscoveryFailure(LogRecordListener log) { var rootCause = new RuntimeException(); var engine = new TestEngineStub("some-engine") { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { throw rootCause; } }; var request = request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .build(); var launcher = createLauncher(engine); launcher.discover(request); var logRecord = log.stream(LoggingLauncherDiscoveryListener.class, Level.SEVERE).findFirst().get(); assertThat(logRecord.getMessage()).isEqualTo("TestEngine with ID 'some-engine' failed to discover tests"); assertThat(logRecord.getThrown()).isSameAs(rootCause); } @Test void logsTraceMessageOnStartAndEnd(LogRecordListener log) { var engine = new TestEngineStub("some-engine"); var request = request() // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .build(); var launcher = createLauncher(engine); launcher.discover(request); assertThat(log.stream(LoggingLauncherDiscoveryListener.class, Level.FINER)) // .extracting(LogRecord::getMessage) // .containsExactly( // "Test discovery started", // "Engine [engine:some-engine] has started discovering tests", // "Engine [engine:some-engine] has finished discovering tests", // "Test discovery finished"); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/session/000077500000000000000000000000001455764576500317425ustar00rootroot00000000000000CompositeLauncherSessionListenerTests.java000066400000000000000000000027771455764576500422640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/listeners/session/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.listeners.session; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import java.util.List; import org.junit.jupiter.api.Test; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.mockito.InOrder; public class CompositeLauncherSessionListenerTests { @Test void callsListenersInReverseOrderForClosedEvents() { var firstListener = mock(LauncherSessionListener.class, "firstListener"); var secondListener = mock(LauncherSessionListener.class, "secondListener"); var launcherSession = mock(LauncherSession.class); var composite = new CompositeLauncherSessionListener(List.of(firstListener, secondListener)); composite.launcherSessionOpened(launcherSession); composite.launcherSessionClosed(launcherSession); InOrder inOrder = inOrder(firstListener, secondListener); inOrder.verify(firstListener).launcherSessionOpened(launcherSession); inOrder.verify(secondListener).launcherSessionOpened(launcherSession); inOrder.verify(secondListener).launcherSessionClosed(launcherSession); inOrder.verify(firstListener).launcherSessionClosed(launcherSession); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/000077500000000000000000000000001455764576500311425ustar00rootroot00000000000000ParserErrorTests.java000066400000000000000000000100361455764576500352170ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; class ParserErrorTests { private final Parser parser = new Parser(); @Test void cantParseExpressionFromNull() { assertThat(parseErrorFromParsing(null)).contains("empty tag expression"); } @Test void emptyExpression() { assertThat(parseErrorFromParsing("")).contains("empty tag expression"); } @Test void missingClosingParenthesis() { assertThat(parseErrorFromParsing("(")).contains("missing closing parenthesis for '(' at index <0>"); assertThat(parseErrorFromParsing("( foo & bar")).contains("missing closing parenthesis for '(' at index <0>"); } @Test void missingOpeningParenthesis() { assertThat(parseErrorFromParsing(")")).contains("missing opening parenthesis for ')' at index <0>"); assertThat(parseErrorFromParsing(" foo | bar)")).contains("missing opening parenthesis for ')' at index <10>"); } @Test void partialUnaryOperator() { assertThat(parseErrorFromParsing("!")).contains("missing rhs operand for '!' at index <0>"); } @Test void partialBinaryOperator() { assertThat(parseErrorFromParsing("& foo")).contains("missing lhs operand for '&' at index <0>"); assertThat(parseErrorFromParsing("foo |")).contains("missing rhs operand for '|' at index <4>"); } @ParameterizedTest @MethodSource("data") void acceptanceTests(String tagExpression, String parseError) { assertThat(parseErrorFromParsing(tagExpression)).contains(parseError); } @SuppressWarnings("unused") private static Stream data() { // @formatter:off return Stream.of( arguments("&", "missing lhs and rhs operand for '&' at index <0>"), arguments("|", "missing lhs and rhs operand for '|' at index <0>"), arguments("| |", "missing lhs and rhs operand for '|' at index <0>"), arguments("!", "missing rhs operand for '!' at index <0>"), arguments("foo bar", "missing operator between 'foo' at index <2> and 'bar' at index <4>"), arguments("foo bar |", "missing rhs operand for '|' at index <8>"), arguments("foo bar | baz", "missing operator between 'foo' at index <2> and '(bar | baz)' at index <4>"), arguments("foo bar &", "missing rhs operand for '&' at index <8>"), arguments("foo & (bar !)", "missing rhs operand for '!' at index <11>"), arguments("( foo & bar ) )", "missing opening parenthesis for ')' at index <14>"), arguments("( ( foo & bar )", "missing closing parenthesis for '(' at index <0>"), arguments("foo & (bar baz) |", "missing operator between 'bar' at index <9> and 'baz' at index <11>"), arguments("foo & (bar baz) &", "missing operator between 'bar' at index <9> and 'baz' at index <11>"), arguments("foo & (bar |baz) &", "missing rhs operand for '&' at index <17>"), arguments("foo | (bar baz) &", "missing rhs operand for '&' at index <16>"), arguments("foo | (bar baz) &quux", "missing operator between 'bar' at index <9> and '(baz & quux)' at index <11>"), arguments("foo & |", "missing rhs operand for '&' at index <4>"), arguments("foo !& bar", "missing rhs operand for '!' at index <4>"), arguments("foo !| bar", "missing rhs operand for '!' at index <4>") ); // @formatter:on } private String parseErrorFromParsing(String tagExpression) { try { var parseResult = parser.parse(tagExpression); parseResult.tagExpressionOrThrow(RuntimeException::new); return null; } catch (RuntimeException ex) { return ex.getMessage(); } } } ParserTests.java000066400000000000000000000051021455764576500342030ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; class ParserTests { private final Parser parser = new Parser(); @Test void notHasHigherPrecedenceThanAnd() { assertThat(tagExpressionParsedFrom("! foo & bar")).hasToString("(!foo & bar)"); } @Test void andHasHigherPrecedenceThanOr() { assertThat(tagExpressionParsedFrom("foo | bar & baz")).hasToString("(foo | (bar & baz))"); } @Test void notIsRightAssociative() { assertThat(tagExpressionParsedFrom("foo &! bar")).hasToString("(foo & !bar)"); } @Test void andIsLeftAssociative() { assertThat(tagExpressionParsedFrom("foo & bar & baz")).hasToString("((foo & bar) & baz)"); } @Test void orIsLeftAssociative() { assertThat(tagExpressionParsedFrom("foo | bar | baz")).hasToString("((foo | bar) | baz)"); } @ParameterizedTest @MethodSource("data") void acceptanceTests(String tagExpression, String expression) { assertThat(tagExpressionParsedFrom(tagExpression)).hasToString(expression); } @SuppressWarnings("unused") private static Stream data() { // @formatter:off return Stream.of( arguments("foo", "foo"), arguments("! foo", "!foo"), arguments("foo & bar", "(foo & bar)"), arguments("foo | bar", "(foo | bar)"), arguments("( ! foo & bar | baz)", "((!foo & bar) | baz)"), arguments("(foo & bar ) | baz & quux", "((foo & bar) | (baz & quux))"), arguments("! foo | bar & ! baz | ! quux | quuz & corge", "(((!foo | (bar & !baz)) | !quux) | (quuz & corge))"), arguments("(foo & bar ) | baz & quux", "((foo & bar) | (baz & quux))"), arguments("foo | bar & baz|quux", "((foo | (bar & baz)) | quux)"), arguments("any()", "any()"), arguments("! none()", "!none()") ); // @formatter:on } private TagExpression tagExpressionParsedFrom(String tagExpression) { return parser.parse(tagExpression).tagExpressionOrThrow( (error) -> new RuntimeException("[" + tagExpression + "] should be parsable")); } } TagExpressionsTests.java000066400000000000000000000064661455764576500357430ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.TestTag.create; import static org.junit.platform.launcher.tagexpression.TagExpressions.and; import static org.junit.platform.launcher.tagexpression.TagExpressions.any; import static org.junit.platform.launcher.tagexpression.TagExpressions.none; import static org.junit.platform.launcher.tagexpression.TagExpressions.not; import static org.junit.platform.launcher.tagexpression.TagExpressions.or; import static org.junit.platform.launcher.tagexpression.TagExpressions.tag; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.TestTag; class TagExpressionsTests { private static final TagExpression True = tags -> true; private static final TagExpression False = tags -> false; @Test void tagIsJustATestTag() { assertThat(tag("foo")).hasToString("foo"); } @Test void rejectInvalidTestTags() { RuntimeException expected = assertThrows(PreconditionViolationException.class, () -> tag("tags with spaces are not allowed")); assertThat(expected).hasMessageContaining("tags with spaces are not allowed"); } @Test void tagEvaluation() { var tagExpression = tag("foo"); assertThat(tagExpression.evaluate(Set.of(create("foo")))).isTrue(); assertThat(tagExpression.evaluate(Set.of(create("not_foo")))).isFalse(); } @Test void justConcatenateNot() { assertThat(not(tag("foo"))).hasToString("!foo"); assertThat(not(and(tag("foo"), tag("bar")))).hasToString("!(foo & bar)"); assertThat(not(or(tag("foo"), tag("bar")))).hasToString("!(foo | bar)"); } @Test void notEvaluation() { assertThat(not(True).evaluate(Set.of())).isFalse(); assertThat(not(False).evaluate(Set.of())).isTrue(); } @Test void encloseAndWithParenthesis() { assertThat(and(tag("foo"), tag("bar"))).hasToString("(foo & bar)"); } @Test void andEvaluation() { assertThat(and(True, True).evaluate(Set.of())).isTrue(); assertThat(and(True, False).evaluate(Set.of())).isFalse(); assertThat(and(False, onEvaluateThrow()).evaluate(Set.of())).isFalse(); } @Test void encloseOrWithParenthesis() { assertThat(or(tag("foo"), tag("bar"))).hasToString("(foo | bar)"); } @Test void orEvaluation() { assertThat(or(False, False).evaluate(Set.of())).isFalse(); assertThat(or(True, onEvaluateThrow()).evaluate(Set.of())).isTrue(); assertThat(or(False, True).evaluate(Set.of())).isTrue(); } @Test void anyEvaluation() { assertThat(any().evaluate(Set.of())).isFalse(); assertThat(any().evaluate(Set.of(TestTag.create("foo")))).isTrue(); } @Test void noneEvaluation() { assertThat(none().evaluate(Set.of())).isTrue(); assertThat(none().evaluate(Set.of(TestTag.create("foo")))).isFalse(); } private TagExpression onEvaluateThrow() { return tags -> { throw new RuntimeException("should not be evaluated"); }; } } TokenTests.java000066400000000000000000000027611455764576500340370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import org.junit.jupiter.api.Test; class TokenTests { @Test void startIndexOfTokenString() { assertThat(new Token(0, "!").trimmedTokenStartIndex()).isEqualTo(0); assertThat(new Token(0, " !").trimmedTokenStartIndex()).isEqualTo(2); assertThat(new Token(7, "!").trimmedTokenStartIndex()).isEqualTo(7); } @Test void endIndexExclusive() { assertThat(new Token(0, "!").endIndexExclusive()).isEqualTo(1); assertThat(new Token(0, " !").endIndexExclusive()).isEqualTo(3); assertThat(new Token(7, "!").endIndexExclusive()).isEqualTo(8); } @Test void lastCharacterIndex() { assertThat(new Token(0, "!").lastCharacterIndex()).isEqualTo(0); assertThat(new Token(0, " !").lastCharacterIndex()).isEqualTo(2); assertThat(new Token(7, "!").lastCharacterIndex()).isEqualTo(7); } @Test void concatenateTwoTokens() { var tokens = new Tokenizer().tokenize(" ! foo"); var one = tokens.get(0); var two = tokens.get(1); var joined = one.concatenate(two); assertThat(joined.rawString).isEqualTo(" ! foo"); assertThat(joined.startIndex).isEqualTo(0); } } TokenizerTests.java000066400000000000000000000064241455764576500347310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.launcher.tagexpression; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.Test; class TokenizerTests { @Test void nullContainsNoTokens() { assertThat(tokenStringsExtractedFrom(null)).isEmpty(); } @Test void removeLeadingAndTrailingSpaces() { assertThat(tokenStringsExtractedFrom(" tag ")).containsExactly("tag"); } @Test void notIsAReservedKeyword() { assertThat(tokenStringsExtractedFrom("! tag")).containsExactly("!", "tag"); assertThat(tokenStringsExtractedFrom("!tag")).containsExactly("!", "tag"); } @Test void andIsAReservedKeyword() { assertThat(tokenStringsExtractedFrom("one & two")).containsExactly("one", "&", "two"); assertThat(tokenStringsExtractedFrom("one&two")).containsExactly("one", "&", "two"); } @Test void orIsAReservedKeyword() { assertThat(tokenStringsExtractedFrom("one | two")).containsExactly("one", "|", "two"); assertThat(tokenStringsExtractedFrom("one|two")).containsExactly("one", "|", "two"); } @Test void anyAndNoneAreReservedKeywords() { assertThat(tokenStringsExtractedFrom("!(any())")).containsExactly("!", "(", "any()", ")"); assertThat(tokenStringsExtractedFrom("!(none())")).containsExactly("!", "(", "none()", ")"); } @Test void discoverBrackets() { assertThat(tokenStringsExtractedFrom("()")).containsExactly("(", ")"); assertThat(tokenStringsExtractedFrom("(tag)")).containsExactly("(", "tag", ")"); assertThat(tokenStringsExtractedFrom("( tag )")).containsExactly("(", "tag", ")"); assertThat(tokenStringsExtractedFrom("( foo &bar)| (baz& qux )")).containsExactly("(", "foo", "&", "bar", ")", "|", "(", "baz", "&", "qux", ")"); } @Test void extractRawStringWithSpaceCharactersBeforeTheToken() { assertThat(rawStringsExtractedFrom("(")).containsExactly("("); assertThat(rawStringsExtractedFrom(" (")).containsExactly(" ("); assertThat(rawStringsExtractedFrom(" ( foo ")).containsExactly(" (", " foo"); assertThat(rawStringsExtractedFrom("(( (( (")).containsExactly("(", "(", " (", "(", " ("); } @Test void extractStartPositionOfRawString() { assertThat(startIndicesExtractedFrom("(")).containsExactly(0); assertThat(startIndicesExtractedFrom(" ( (")).containsExactly(0, 3); assertThat(startIndicesExtractedFrom("foo &!bar")).containsExactly(0, 3, 5, 6); } private Stream startIndicesExtractedFrom(String expression) { return tokensExtractedFrom(expression).map(token -> token.startIndex); } private Stream rawStringsExtractedFrom(String expression) { return tokensExtractedFrom(expression).map(token -> token.rawString); } private List tokenStringsExtractedFrom(String expression) { return tokensExtractedFrom(expression).map(Token::string).collect(toList()); } private Stream tokensExtractedFrom(String expression) { return new Tokenizer().tokenize(expression).stream(); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/000077500000000000000000000000001455764576500264575ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/000077500000000000000000000000001455764576500277235ustar00rootroot00000000000000LegacyReportingUtilsTests.java000066400000000000000000000075661455764576500356670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.launcher.TestPlan; /** * @since 1.0.3 */ class LegacyReportingUtilsTests { private TestDescriptor engineDescriptor = new EngineDescriptor(UniqueId.forEngine("foo"), "Foo"); @Test void legacyReportingClassNameForTestIdentifierWithoutClassSourceIsParentLegacyReportingName() { var uniqueId = engineDescriptor.getUniqueId().append("child", "bar"); var testDescriptor = createTestDescriptor(uniqueId, "Bar", null); engineDescriptor.addChild(testDescriptor); assertThat(getClassName(engineDescriptor.getUniqueId())).isEqualTo(""); assertThat(getClassName(uniqueId)).isEqualTo("Foo"); assertThat(getClassNameFromOldLocation(engineDescriptor.getUniqueId())).isEqualTo(""); assertThat(getClassNameFromOldLocation(uniqueId)).isEqualTo("Foo"); } @Test void legacyReportingClassNameForDescendantOfTestIdentifierWithClassSourceIsClassName() { var classUniqueId = engineDescriptor.getUniqueId().append("class", "class"); var classDescriptor = createTestDescriptor(classUniqueId, "Class", ClassSource.from(LegacyReportingUtilsTests.class)); engineDescriptor.addChild(classDescriptor); var subUniqueId = classUniqueId.append("sub", "baz"); var subDescriptor = createTestDescriptor(subUniqueId, "Baz", null); classDescriptor.addChild(subDescriptor); var subSubUniqueId = subUniqueId.append("subsub", "qux"); var subSubDescriptor = createTestDescriptor(subSubUniqueId, "Qux", null); subDescriptor.addChild(subSubDescriptor); assertThat(getClassName(engineDescriptor.getUniqueId())).isEqualTo(""); assertThat(getClassName(classUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); assertThat(getClassName(subUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); assertThat(getClassName(subSubUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); assertThat(getClassNameFromOldLocation(engineDescriptor.getUniqueId())).isEqualTo(""); assertThat(getClassNameFromOldLocation(classUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); assertThat(getClassNameFromOldLocation(subUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); assertThat(getClassNameFromOldLocation(subSubUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); } private String getClassName(UniqueId uniqueId) { var testPlan = TestPlan.from(Set.of(engineDescriptor), mock()); return LegacyReportingUtils.getClassName(testPlan, testPlan.getTestIdentifier(uniqueId)); } @SuppressWarnings("deprecation") private String getClassNameFromOldLocation(UniqueId uniqueId) { var testPlan = TestPlan.from(Set.of(engineDescriptor), mock()); return org.junit.platform.launcher.listeners.LegacyReportingUtils.getClassName(testPlan, testPlan.getTestIdentifier(uniqueId)); } private TestDescriptor createTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { return new AbstractTestDescriptor(uniqueId, displayName, source) { @Override public Type getType() { return Type.CONTAINER_AND_TEST; } }; } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/000077500000000000000000000000001455764576500305235ustar00rootroot00000000000000IncrementingClock.java000066400000000000000000000021751455764576500347120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.time.ZoneId; /** * @since 1.0 */ final class IncrementingClock extends Clock { private final Duration duration; private final ZoneId zone; private int counter; IncrementingClock(int start, Duration duration) { this(start, duration, ZoneId.systemDefault()); } private IncrementingClock(int start, Duration duration, ZoneId zone) { this.counter = start; this.duration = duration; this.zone = zone; } @Override public Instant instant() { return Instant.EPOCH.plus(duration.multipliedBy(counter++)); } @Override public Clock withZone(ZoneId zone) { return new IncrementingClock(counter, duration, zone); } @Override public ZoneId getZone() { return zone; } } LegacyXmlReportGeneratingListenerTests.java000066400000000000000000000421761455764576500411370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static org.assertj.core.api.Assertions.assertThat; import static org.joox.JOOX.$; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.junit.platform.reporting.legacy.xml.XmlReportAssertions.assertValidAccordingToJenkinsSchema; import static org.mockito.Mockito.mock; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; import java.time.Year; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.joox.Match; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.engine.support.hierarchical.DemoEngineExecutionContext; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalContainerDescriptor; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestDescriptor; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.LauncherConstants; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.opentest4j.AssertionFailedError; /** * Tests for {@link LegacyXmlReportGeneratingListener}. * * @since 1.0 */ class LegacyXmlReportGeneratingListenerTests { @TempDir Path tempDirectory; @Test void writesFileForSingleSucceedingTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("succeedingTest", "display<-->Name 😎", () -> { }); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("name")).isEqualTo("dummy"); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(0); assertThat(testsuite.attr("failures", int.class)).isEqualTo(0); assertThat(testsuite.attr("errors", int.class)).isEqualTo(0); assertThat(testsuite.child("system-out").text()) // .containsSubsequence("unique-id: [engine:dummy]", "display-name: dummy"); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("display<-->Name 😎"); assertThat(testcase.attr("classname")).isEqualTo("dummy"); assertThat(testcase.child("system-out").text()) // .containsSubsequence("unique-id: [engine:dummy]/[test:succeedingTest]", "display-name: display<-->Name 😎"); assertThat(testsuite.find("skipped")).isEmpty(); assertThat(testsuite.find("failure")).isEmpty(); assertThat(testsuite.find("error")).isEmpty(); } @Test void writesFileForSingleFailingTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("failingTest", () -> fail("expected to fail")); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(0); assertThat(testsuite.attr("failures", int.class)).isEqualTo(1); assertThat(testsuite.attr("errors", int.class)).isEqualTo(0); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("failingTest"); var failure = testcase.child("failure"); assertThat(failure.attr("message")).isEqualTo("expected to fail"); assertThat(failure.attr("type")).isEqualTo(AssertionFailedError.class.getName()); assertThat(failure.text()).containsSubsequence("AssertionFailedError: expected to fail", "\tat"); assertThat(testsuite.find("skipped")).isEmpty(); assertThat(testsuite.find("error")).isEmpty(); } @Test void writesFileForSingleErroneousTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("failingTest", () -> { throw new RuntimeException("error occurred"); }); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(0); assertThat(testsuite.attr("failures", int.class)).isEqualTo(0); assertThat(testsuite.attr("errors", int.class)).isEqualTo(1); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("failingTest"); var error = testcase.child("error"); assertThat(error.attr("message")).isEqualTo("error occurred"); assertThat(error.attr("type")).isEqualTo(RuntimeException.class.getName()); assertThat(error.text()).containsSubsequence("RuntimeException: error occurred", "\tat"); assertThat(testsuite.find("skipped")).isEmpty(); assertThat(testsuite.find("failure")).isEmpty(); } @Test void writesFileForSingleSkippedTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); var testDescriptor = engine.addTest("skippedTest", () -> fail("never called")); testDescriptor.markSkipped("should be skipped"); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(1); assertThat(testsuite.attr("failures", int.class)).isEqualTo(0); assertThat(testsuite.attr("errors", int.class)).isEqualTo(0); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("skippedTest"); assertThat(testcase.child("skipped").text()).isEqualTo("should be skipped"); assertThat(testsuite.find("failure")).isEmpty(); assertThat(testsuite.find("error")).isEmpty(); } @SuppressWarnings("ConstantConditions") @Test void writesFileForSingleAbortedTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("abortedTest", () -> assumeFalse(true, "deliberately aborted")); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(1); assertThat(testsuite.attr("failures", int.class)).isEqualTo(0); assertThat(testsuite.attr("errors", int.class)).isEqualTo(0); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("abortedTest"); assertThat(testcase.child("skipped").text()) // .containsSubsequence("TestAbortedException: ", "deliberately aborted", "at "); assertThat(testsuite.find("failure")).isEmpty(); assertThat(testsuite.find("error")).isEmpty(); } @Test void measuresTimesInSeconds() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("firstTest", () -> { }); engine.addTest("secondTest", () -> { }); executeTests(engine, new IncrementingClock(0, Duration.ofMillis(333))); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); // start end // ----------- ---------- ----------- // engine 0 (1) 1,665 (6) // firstTest 333 (2) 666 (3) // secondTest 999 (4) 1,332 (5) assertThat(testsuite.attr("time", double.class)) // .isEqualTo(1.665); assertThat(testsuite.children("testcase").matchAttr("name", "firstTest").attr("time", double.class)) // .isEqualTo(0.333); assertThat(testsuite.children("testcase").matchAttr("name", "secondTest").attr("time", double.class)) // .isEqualTo(0.333); } @Test void testWithImmeasurableTimeIsOutputCorrectly() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("test", () -> { }); executeTests(engine, Clock.fixed(Instant.EPOCH, ZoneId.systemDefault())); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.child("testcase").attr("time")).isEqualTo("0"); } @Test void writesFileForSkippedContainer() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("test", () -> fail("never called")); engine.getEngineDescriptor().markSkipped("should be skipped"); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("skipped", int.class)).isEqualTo(1); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("test"); assertThat(testcase.child("skipped").text()).isEqualTo("parent was skipped: should be skipped"); } @Test void writesFileForFailingContainer() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("test", () -> fail("never called")); engine.getEngineDescriptor().setBeforeAllBehavior(() -> fail("failure before all tests")); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("failures", int.class)).isEqualTo(1); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("test"); var failure = testcase.child("failure"); assertThat(failure.attr("message")).isEqualTo("failure before all tests"); assertThat(failure.attr("type")).isEqualTo(AssertionFailedError.class.getName()); assertThat(failure.text()).containsSubsequence("AssertionFailedError: failure before all tests", "\tat"); } @Test void writesFileForFailingContainerWithoutTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addContainer("failingContainer", () -> { throw new RuntimeException("boom"); }); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("errors", int.class)).isEqualTo(1); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("failingContainer"); assertThat(testcase.attr("classname")).isEqualTo("dummy"); var error = testcase.child("error"); assertThat(error.attr("message")).isEqualTo("boom"); assertThat(error.attr("type")).isEqualTo(RuntimeException.class.getName()); assertThat(error.text()).containsSubsequence("RuntimeException: boom", "\tat"); } @Test void writesFileForContainerFailingAfterTest() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); var container = engine.addChild("failingContainer", uniqueId -> new DemoHierarchicalContainerDescriptor(uniqueId, "failingContainer", null, null) { @Override public void after(DemoEngineExecutionContext context) { throw new RuntimeException("boom"); } }, "child"); container.addChild(new DemoHierarchicalTestDescriptor(container.getUniqueId().append("test", "someTest"), "someTest", (c, t) -> { })); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("tests", int.class)).isEqualTo(1); assertThat(testsuite.attr("errors", int.class)).isEqualTo(1); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("someTest"); assertThat(testcase.attr("classname")).isEqualTo("failingContainer"); var error = testcase.child("error"); assertThat(error.attr("message")).isEqualTo("boom"); assertThat(error.attr("type")).isEqualTo(RuntimeException.class.getName()); assertThat(error.text()).containsSubsequence("RuntimeException: boom", "\tat"); } @Test void writesSystemProperties() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("test", () -> { }); executeTests(engine); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); var properties = testsuite.child("properties").children("property"); assertThat(properties.matchAttr("name", "file\\.separator").attr("value")).isEqualTo(File.separator); assertThat(properties.matchAttr("name", "path\\.separator").attr("value")).isEqualTo(File.pathSeparator); } @Test void writesHostNameAndTimestamp() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("test", () -> { }); var now = LocalDateTime.parse("2016-01-28T14:02:59.123"); var zone = ZoneId.systemDefault(); executeTests(engine, Clock.fixed(ZonedDateTime.of(now, zone).toInstant(), zone)); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-dummy.xml")); assertThat(testsuite.attr("hostname")).isEqualTo(InetAddress.getLocalHost().getHostName()); assertThat(testsuite.attr("timestamp")).isEqualTo("2016-01-28T14:02:59"); } @Test void printsExceptionWhenReportsDirCannotBeCreated() throws Exception { var reportsDir = tempDirectory.resolve("dummy.txt"); Files.write(reportsDir, Set.of("content")); var out = new StringWriter(); var listener = new LegacyXmlReportGeneratingListener(reportsDir, new PrintWriter(out)); listener.testPlanExecutionStarted(TestPlan.from(Set.of(), mock())); assertThat(out.toString()).containsSubsequence("Could not create reports directory", "FileAlreadyExistsException", "at "); } @Test void printsExceptionWhenReportCouldNotBeWritten() throws Exception { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var xmlFile = tempDirectory.resolve("TEST-engine.xml"); Files.createDirectories(xmlFile); var out = new StringWriter(); var listener = new LegacyXmlReportGeneratingListener(tempDirectory, new PrintWriter(out)); listener.testPlanExecutionStarted(TestPlan.from(Set.of(engineDescriptor), mock())); listener.executionFinished(TestIdentifier.from(engineDescriptor), successful()); assertThat(out.toString()).containsSubsequence("Could not write XML report", "Exception", "at "); } @Test void writesReportEntriesToSystemOutElement() throws Exception { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var childUniqueId = UniqueId.root("child", "test"); engineDescriptor.addChild(new TestDescriptorStub(childUniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), mock()); var out = new StringWriter(); var listener = new LegacyXmlReportGeneratingListener(tempDirectory, new PrintWriter(out)); listener.testPlanExecutionStarted(testPlan); var testIdentifier = testPlan.getTestIdentifier(childUniqueId); listener.executionStarted(testIdentifier); listener.reportingEntryPublished(testIdentifier, ReportEntry.from("foo", "bar")); Map map = new LinkedHashMap<>(); map.put("bar", "baz"); map.put("qux", "foo"); listener.reportingEntryPublished(testIdentifier, ReportEntry.from(map)); listener.executionFinished(testIdentifier, successful()); listener.executionFinished(testPlan.getTestIdentifier(engineDescriptor.getUniqueId()), successful()); var testsuite = readValidXmlFile(tempDirectory.resolve("TEST-engine.xml")); assertThat(String.join("\n", testsuite.child("testcase").children("system-out").texts())) // .containsSubsequence( // "Report Entry #1 (timestamp: " + Year.now(), "- foo: bar\n", "Report Entry #2 (timestamp: " + Year.now(), "- bar: baz\n", "- qux: foo\n"); } private void executeTests(TestEngine engine) { executeTests(engine, Clock.systemDefaultZone()); } private void executeTests(TestEngine engine, Clock clock) { var out = new PrintWriter(new StringWriter()); var reportListener = new LegacyXmlReportGeneratingListener(tempDirectory.toString(), out, clock); var launcher = createLauncher(engine); launcher.registerTestExecutionListeners(reportListener); launcher.execute(request().configurationParameter(LauncherConstants.STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME, "false").selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))).build()); } private Match readValidXmlFile(Path xmlFile) throws Exception { assertTrue(Files.exists(xmlFile), () -> "File does not exist: " + xmlFile); try (var reader = Files.newBufferedReader(xmlFile)) { var xml = $(reader); assertValidAccordingToJenkinsSchema(xml.document()); return xml; } } } XmlReportAssertions.java000066400000000000000000000031321455764576500353150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static org.junit.jupiter.api.Assertions.fail; import javax.xml.XMLConstants; import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * @since 1.0 */ class XmlReportAssertions { static void assertValidAccordingToJenkinsSchema(Document document) throws Exception { try { // Schema is thread-safe, Validator is not var validator = CachedSchema.JENKINS.newValidator(); validator.validate(new DOMSource(document)); } catch (SAXException e) { fail("Invalid XML document: " + document, e); } } private enum CachedSchema { JENKINS("/jenkins-junit.xsd"); private final Schema schema; CachedSchema(String resourcePath) { var schemaFile = LegacyXmlReportGeneratingListener.class.getResource(resourcePath); var schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); try { this.schema = schemaFactory.newSchema(schemaFile); } catch (SAXException e) { throw new RuntimeException("Failed to create schema using " + schemaFile, e); } } Validator newValidator() { return schema.newValidator(); } } } XmlReportDataTests.java000066400000000000000000000060351455764576500350640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.mockito.Mockito.mock; import java.time.Clock; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class XmlReportDataTests { private final ConfigurationParameters configParams = mock(); @Test void resultsOfTestIdentifierWithoutAnyReportedEventsAreEmpty() { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var childUniqueId = UniqueId.root("child", "test"); engineDescriptor.addChild(new TestDescriptorStub(childUniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var results = reportData.getResults(testPlan.getTestIdentifier(childUniqueId)); assertThat(results).isEmpty(); } @Test void resultsOfTestIdentifierWithoutReportedEventsContainsOnlyFailureOfAncestor() { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var childUniqueId = UniqueId.root("child", "test"); engineDescriptor.addChild(new TestDescriptorStub(childUniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var failureOfAncestor = failed(new RuntimeException("failed!")); reportData.markFinished(testPlan.getTestIdentifier(engineDescriptor.getUniqueId()), failureOfAncestor); var results = reportData.getResults(testPlan.getTestIdentifier(childUniqueId)); assertThat(results).containsExactly(failureOfAncestor); } @Test void resultsOfTestIdentifierWithoutReportedEventsContainsOnlySuccessOfAncestor() { var engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); var childUniqueId = UniqueId.root("child", "test"); engineDescriptor.addChild(new TestDescriptorStub(childUniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); reportData.markFinished(testPlan.getTestIdentifier(engineDescriptor.getUniqueId()), successful()); var results = reportData.getResults(testPlan.getTestIdentifier(childUniqueId)); assertThat(results).containsExactly(successful()); } } XmlReportWriterTests.java000066400000000000000000000263751455764576500355000ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/legacy/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.legacy.xml; import static org.assertj.core.api.Assertions.assertThat; import static org.joox.JOOX.$; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.LauncherConstants.STDOUT_REPORT_ENTRY_KEY; import static org.junit.platform.reporting.legacy.xml.XmlReportAssertions.assertValidAccordingToJenkinsSchema; import static org.mockito.Mockito.mock; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.time.Clock; import java.util.Map; import java.util.Set; import java.util.stream.Stream; import org.joox.Match; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ class XmlReportWriterTests { private final ConfigurationParameters configParams = mock(); private EngineDescriptor engineDescriptor = new EngineDescriptor(UniqueId.forEngine("engine"), "Engine"); @Test void writesTestsuiteElementsWithoutTestcaseElementsWithoutAnyTests() throws Exception { var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); assertThat(testsuite.document().getDocumentElement().getTagName()).isEqualTo("testsuite"); assertThat(testsuite.attr("name")).isEqualTo("Engine"); assertThat(testsuite.attr("tests", int.class)).isEqualTo(0); assertThat(testsuite.find("testcase")).isEmpty(); } @Test void writesReportEntry() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); var testDescriptor = new TestDescriptorStub(uniqueId, "successfulTest"); engineDescriptor.addChild(testDescriptor); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); reportData.addReportEntry(TestIdentifier.from(testDescriptor), ReportEntry.from("myKey", "myValue")); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), successful()); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); assertThat(String.join("\n", testsuite.find("system-out").texts())) // .containsSubsequence("Report Entry #1 (timestamp: ", "- myKey: myValue"); } @Test void writesCapturedOutput() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); var testDescriptor = new TestDescriptorStub(uniqueId, "successfulTest"); engineDescriptor.addChild(testDescriptor); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var reportEntry = ReportEntry.from(Map.of( // STDOUT_REPORT_ENTRY_KEY, "normal output", // STDERR_REPORT_ENTRY_KEY, "error output", // "foo", "bar")); reportData.addReportEntry(TestIdentifier.from(testDescriptor), reportEntry); reportData.addReportEntry(TestIdentifier.from(testDescriptor), ReportEntry.from(Map.of("baz", "qux"))); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), successful()); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); assertThat(testsuite.find("system-out").text(0)) // .containsSubsequence("unique-id: ", "test:test", "display-name: successfulTest"); assertThat(testsuite.find("system-out").text(1)) // .containsSubsequence("Report Entry #1 (timestamp: ", "- foo: bar", "Report Entry #2 (timestamp: ", "- baz: qux"); assertThat(testsuite.find("system-out").text(2).trim()) // .isEqualTo("normal output"); assertThat(testsuite.find("system-err").text().trim()) // .isEqualTo("error output"); } @Test void writesEmptySkippedElementForSkippedTestWithoutReason() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "skippedTest")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); reportData.markSkipped(testPlan.getTestIdentifier(uniqueId), null); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("skippedTest"); var skipped = testcase.child("skipped"); assertThat(skipped.size()).isEqualTo(1); assertThat(skipped.children()).isEmpty(); } @Test void writesEmptyErrorElementForFailedTestWithoutCause() throws Exception { engineDescriptor = new EngineDescriptor(UniqueId.forEngine("myEngineId"), "Fancy Engine") { @Override public String getLegacyReportingName() { return "myEngine"; } }; var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "some fancy name") { @Override public String getLegacyReportingName() { return "failedTest"; } }); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), failed(null)); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); var testcase = testsuite.child("testcase"); assertThat(testcase.attr("name")).isEqualTo("failedTest"); assertThat(testcase.attr("classname")).isEqualTo("myEngine"); var error = testcase.child("error"); assertThat(error.size()).isEqualTo(1); assertThat(error.children()).isEmpty(); } @Test void omitsMessageAttributeForFailedTestWithThrowableWithoutMessage() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "failedTest")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), failed(new NullPointerException())); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); var error = testsuite.find("error"); assertThat(error.attr("type")).isEqualTo("java.lang.NullPointerException"); assertThat(error.attr("message")).isNull(); } @Test void writesValidXmlEvenIfExceptionMessageContainsCData() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var assertionError = new AssertionError(""); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), failed(assertionError)); var testsuite = writeXmlReport(testPlan, reportData); assertValidAccordingToJenkinsSchema(testsuite.document()); assertThat(testsuite.find("failure").attr("message")).isEqualTo(""); } @Test void escapesInvalidCharactersInSystemPropertiesAndExceptionMessages() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var assertionError = new AssertionError("expected: but was: "); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), failed(assertionError)); System.setProperty("foo.bar", "\1"); Match testsuite; try { testsuite = writeXmlReport(testPlan, reportData); } finally { System.getProperties().remove("foo.bar"); } assertValidAccordingToJenkinsSchema(testsuite.document()); assertThat(testsuite.find("property").matchAttr("name", "foo\\.bar").attr("value")) // .isEqualTo(""); var failure = testsuite.find("failure"); assertThat(failure.attr("message")) // .isEqualTo("expected: but was: "); assertThat(failure.text()) // .contains("AssertionError: expected: but was: "); } @Test void doesNotReopenCDataWithinCDataContent() throws Exception { var uniqueId = engineDescriptor.getUniqueId().append("test", "test"); engineDescriptor.addChild(new TestDescriptorStub(uniqueId, "test")); var testPlan = TestPlan.from(Set.of(engineDescriptor), configParams); var reportData = new XmlReportData(testPlan, Clock.systemDefaultZone()); var assertionError = new AssertionError(""); reportData.markFinished(testPlan.getTestIdentifier(uniqueId), failed(assertionError)); Writer assertingWriter = new StringWriter() { @SuppressWarnings("NullableProblems") @Override public void write(char[] buffer, int off, int len) { assertThat(new String(buffer, off, len)).doesNotContain("]]> stringPairs() { return Stream.of( // arguments("\0", "�"), // arguments("\1", ""), // arguments("\t", "\t"), // arguments("\r", "\r"), // arguments("\n", "\n"), // arguments("\u001f", ""), // arguments("\u0020", "\u0020"), // arguments("foo!", "foo!"), // arguments("\uD801\uDC00", "\uD801\uDC00") // ); } private Match writeXmlReport(TestPlan testPlan, XmlReportData reportData) throws Exception { var out = new StringWriter(); writeXmlReport(testPlan, reportData, out); return $(new StringReader(out.toString())); } private void writeXmlReport(TestPlan testPlan, XmlReportData reportData, Writer out) throws Exception { new XmlReportWriter(reportData).writeXmlReport(getOnlyElement(testPlan.getRoots()), out); } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/open/000077500000000000000000000000001455764576500274205ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/000077500000000000000000000000001455764576500302205ustar00rootroot00000000000000OpenTestReportGeneratingListenerTests.java000066400000000000000000000136611455764576500405050ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.reporting.open.xml; import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.JRE.JAVA_22; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener.ENABLED_PROPERTY_NAME; import static org.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener.OUTPUT_DIR_PROPERTY_NAME; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.opentest4j.reporting.tooling.validator.DefaultValidator; import org.opentest4j.reporting.tooling.validator.ValidationResult; import org.xmlunit.assertj3.XmlAssert; import org.xmlunit.placeholder.PlaceholderDifferenceEvaluator; /** * Tests for {@link OpenTestReportGeneratingListener}. * * @since 1.9 */ @DisabledForJreRange(min = JAVA_22, disabledReason = "https://github.com/junit-team/junit5/issues/3594") public class OpenTestReportGeneratingListenerTests { @TempDir(cleanup = ON_SUCCESS) Path tempDirectory; @Test void writesValidXmlReport() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("failingTest", "display<-->Name 😎", (context, descriptor) -> { var listener = context.request.getEngineExecutionListener(); listener.reportingEntryPublished(descriptor, ReportEntry.from("key", "value")); fail("failure message"); }); executeTests(engine); var xmlFile = findXmlReport(); assertThat(validate(xmlFile)).isEmpty(); var expected = """ ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} [engine:dummy] dummy CONTAINER [engine:dummy]/[test:failingTest] display<-->Name 😎 TEST value ${xmlunit.matchesRegex(org\\.opentest4j\\.AssertionFailedError: failure message)} """; XmlAssert.assertThat(xmlFile).and(expected) // .withDifferenceEvaluator(new PlaceholderDifferenceEvaluator()) // .ignoreWhitespace() // .areIdentical(); } private ValidationResult validate(Path xmlFile) throws URISyntaxException { var catalogUri = requireNonNull(getClass().getResource("catalog.xml")).toURI(); return new DefaultValidator(catalogUri).validate(xmlFile); } private void executeTests(TestEngine engine) { var build = request() // .selectors(selectUniqueId(UniqueId.forEngine(engine.getId()))) // .configurationParameter(ENABLED_PROPERTY_NAME, String.valueOf(true)) // .configurationParameter(OUTPUT_DIR_PROPERTY_NAME, tempDirectory.toString()) // .build(); createLauncher(engine).execute(build, new OpenTestReportGeneratingListener()); } private Path findXmlReport() throws IOException { try (var stream = Files.list(tempDirectory)) { return stream.findAny().orElseThrow(AssertionError::new); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/runner/000077500000000000000000000000001455764576500257575ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/runner/JUnitPlatformRunnerTests.java000066400000000000000000001020211455764576500335710ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.runner; import static java.util.stream.Collectors.toSet; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; import static org.junit.runner.Description.createSuiteDescription; import static org.junit.runner.Description.createTestDescription; import static org.junit.runner.manipulation.Filter.matchMethodDescription; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; import java.util.Set; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.Filter; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestDescriptor; import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; import org.junit.platform.fakes.TestDescriptorStub; import org.junit.platform.fakes.TestEngineStub; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestPlan; import org.junit.platform.suite.api.ExcludeClassNamePatterns; import org.junit.platform.suite.api.ExcludeEngines; import org.junit.platform.suite.api.ExcludePackages; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.IncludePackages; import org.junit.platform.suite.api.IncludeTags; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.platform.suite.api.UseTechnicalNames; import org.junit.runner.Description; import org.junit.runner.manipulation.NoTestsRemainException; import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; import org.mockito.ArgumentCaptor; /** * Tests for the {@link JUnitPlatform} runner. * * @since 1.0 */ @Tag("junit4") @SuppressWarnings("deprecation") class JUnitPlatformRunnerTests { @Nested class Discovery { @Test void requestsClassSelectorForAnnotatedClassWhenNoAdditionalAnnotationsArePresent() { class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var selectors = request.getSelectorsByType(ClassSelector.class); assertThat(selectors).hasSize(1); var classSelector = getOnlyElement(selectors); assertEquals(TestCase.class, classSelector.getJavaClass()); } @Test void requestsClassSelectorsWhenSelectClassesAnnotationIsPresent() { @SelectClasses({ Short.class, Byte.class }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var selectors = request.getSelectorsByType(ClassSelector.class); assertThat(selectors).hasSize(2); assertEquals(Short.class, selectors.get(0).getJavaClass()); assertEquals(Byte.class, selectors.get(1).getJavaClass()); } @Test void updatesIncludeClassNameFilterWhenSelectClassesAnnotationIsPresent() { @SelectClasses({ Short.class, Byte.class }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).hasSize(1); var filter = filters.get(0); // Excluded by default assertExcludes(filter, "example.MyClass"); assertExcludes(filter, "example.MyTestClass"); assertExcludes(filter, "example.Short"); assertExcludes(filter, "example.Byte"); // Included due to ClassNameFilter.STANDARD_INCLUDE_PATTERN assertIncludes(filter, "TestClass"); assertIncludes(filter, "example.TestClass"); assertIncludes(filter, "example.MyTests"); assertIncludes(filter, "example.MyTest"); // Included due to @SelectClasses({ Short.class, Byte.class }) assertIncludes(filter, Short.class.getName()); assertIncludes(filter, Byte.class.getName()); } @Test void requestsPackageSelectorsWhenPackagesAnnotationIsPresent() { @SelectPackages({ "foo", "bar" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var selectors = request.getSelectorsByType(PackageSelector.class); assertThat(selectors).hasSize(2); assertEquals("foo", selectors.get(0).getPackageName()); assertEquals("bar", selectors.get(1).getPackageName()); } @Test void addsPackageFiltersToRequestWhenIncludePackageAnnotationIsPresent() { @IncludePackages({ "includedpackage1", "includedpackage2" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(PackageNameFilter.class); assertThat(filters).hasSize(1); var filter = filters.get(0); assertIncludes(filter, "includedpackage1.TestClass"); assertIncludes(filter, "includedpackage2.TestClass"); assertExcludes(filter, "excludedpackage1.TestClass"); } @Test void addsPackageFiltersToRequestWhenExcludePackageAnnotationIsPresent() { @ExcludePackages({ "excludedpackage1", "excludedpackage2" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(PackageNameFilter.class); assertThat(filters).hasSize(1); var filter = filters.get(0); assertIncludes(filter, "includedpackage1.TestClass"); assertExcludes(filter, "excludedpackage1.TestClass"); assertExcludes(filter, "excludedpackage2.TestClass"); } @Test void addsTagFilterToRequestWhenIncludeTagsAnnotationIsPresent() { @IncludeTags({ "foo", "bar" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getPostDiscoveryFilters(); assertThat(filters).hasSize(1); var filter = filters.get(0); assertIncludes(filter, testDescriptorWithTags("foo")); assertIncludes(filter, testDescriptorWithTags("bar")); assertExcludes(filter, testDescriptorWithTags("baz")); } @Test void addsTagFilterToRequestWhenExcludeTagsAnnotationIsPresent() { @ExcludeTags({ "foo", "bar" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getPostDiscoveryFilters(); assertThat(filters).hasSize(1); var filter = filters.get(0); assertExcludes(filter, testDescriptorWithTags("foo")); assertExcludes(filter, testDescriptorWithTags("bar")); assertIncludes(filter, testDescriptorWithTags("baz")); } @Test void includeTagsAcceptsTagExpressions() { @IncludeTags("foo & !bar") class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getPostDiscoveryFilters(); assertThat(filters).hasSize(1); var filter = filters.get(0); assertIncludes(filter, testDescriptorWithTags("foo")); assertIncludes(filter, testDescriptorWithTags("foo", "any_other_tag")); assertExcludes(filter, testDescriptorWithTags("foo", "bar")); assertExcludes(filter, testDescriptorWithTags("bar")); assertExcludes(filter, testDescriptorWithTags("bar", "any_other_tag")); } @Test void excludeTagsAcceptsTagExpressions() { @ExcludeTags("foo & !bar") class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getPostDiscoveryFilters(); assertThat(filters).hasSize(1); var filter = filters.get(0); assertExcludes(filter, testDescriptorWithTags("foo")); assertExcludes(filter, testDescriptorWithTags("foo", "any_other_tag")); assertIncludes(filter, testDescriptorWithTags("foo", "bar")); assertIncludes(filter, testDescriptorWithTags("bar")); assertIncludes(filter, testDescriptorWithTags("bar", "any_other_tag")); } @Test void addsEngineFiltersToRequestWhenIncludeEnginesOrExcludeEnginesAnnotationsArePresent() { @IncludeEngines({ "foo", "bar", "baz" }) @ExcludeEngines({ "bar", "quux" }) class TestCase { } TestEngine fooEngine = new TestEngineStub("foo"); TestEngine barEngine = new TestEngineStub("bar"); TestEngine bazEngine = new TestEngineStub("baz"); TestEngine quuxEngine = new TestEngineStub("quux"); var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getEngineFilters(); assertThat(filters).hasSize(2); var includeFilter = filters.get(1); assertIncludes(includeFilter, fooEngine); assertIncludes(includeFilter, barEngine); assertIncludes(includeFilter, bazEngine); assertExcludes(includeFilter, quuxEngine); var excludeFilter = filters.get(0); assertIncludes(excludeFilter, fooEngine); assertExcludes(excludeFilter, barEngine); assertIncludes(excludeFilter, bazEngine); assertExcludes(excludeFilter, quuxEngine); } @Test void addsDefaultClassNameFilterToRequestWhenFilterClassNameAnnotationIsNotPresentOnTestSuite() { @SelectPackages("foo") class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(STANDARD_INCLUDE_PATTERN); } @Test void addsDefaultClassNameFilterToRequestWhenFilterClassNameAnnotationIsNotPresentOnTestClass() { class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).isEmpty(); } @Test void addsSingleExplicitClassNameFilterToRequestWhenIncludeClassNamePatternsAnnotationIsPresent() { @IncludeClassNamePatterns(".*Foo") class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(".*Foo"); } @Test void addsSingleClassNameFilterToRequestWhenExcludeClassNamePatternsAnnotationIsPresent() { @ExcludeClassNamePatterns(".*Foo") class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(".*Foo"); } @Test void addsMultipleExplicitClassNameFilterToRequestWhenIncludeClassNamePatternsAnnotationIsPresent() { @IncludeClassNamePatterns({ ".*Foo", "Bar.*" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(".*Foo", "Bar.*"); } @Test void addsMultipleClassNameFilterToRequestWhenExcludeClassNamePatternsAnnotationIsPresent() { @ExcludeClassNamePatterns({ ".*Foo", "Bar.*" }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(".*Foo", "Bar.*"); } @Test void usesStandardIncludePatternWhenIncludeClassNamePatternsAnnotationIsPresentWithoutArguments() { @IncludeClassNamePatterns class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains(STANDARD_INCLUDE_PATTERN); } @Test void doesNotAddClassNameFilterWhenIncludeClassNamePatternsAnnotationIsPresentWithEmptyArguments() { @IncludeClassNamePatterns({}) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).isEmpty(); } @Test void doesNotAddClassNameFilterWhenExcludeClassNamePatternsAnnotationIsPresentWithEmptyArguments() { @ExcludeClassNamePatterns({}) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(filters).isEmpty(); } @Test void trimsArgumentsOfIncludeClassNamePatternsAnnotation() { @IncludeClassNamePatterns({ " foo", "bar " }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains("'foo'", "'bar'"); } @Test void trimsArgumentsOfExcludeClassNamePatternsAnnotation() { @ExcludeClassNamePatterns({ " foo", "bar " }) class TestCase { } var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); var filters = request.getFiltersByType(ClassNameFilter.class); assertThat(getOnlyElement(filters).toString()).contains("'foo'", "'bar'"); } @Test void convertsTestIdentifiersIntoDescriptions() { TestDescriptor container1 = new TestDescriptorStub(UniqueId.root("root", "container1"), "container1"); container1.addChild(new TestDescriptorStub(UniqueId.root("root", "test1"), "test1")); TestDescriptor container2 = new TestDescriptorStub(UniqueId.root("root", "container2"), "container2"); container2.addChild(new TestDescriptorStub(UniqueId.root("root", "test2a"), "test2a")); container2.addChild(new TestDescriptorStub(UniqueId.root("root", "test2b"), "test2b")); var testPlan = TestPlan.from(List.of(container1, container2), mock()); var launcher = mock(Launcher.class); when(launcher.discover(any())).thenReturn(testPlan); var runner = new JUnitPlatform(TestClass.class, launcher); var runnerDescription = runner.getDescription(); assertEquals(createSuiteDescription(TestClass.class), runnerDescription); List containerDescriptions = runnerDescription.getChildren(); assertThat(containerDescriptions).hasSize(2); assertEquals(suiteDescription("[root:container1]"), containerDescriptions.get(0)); assertEquals(suiteDescription("[root:container2]"), containerDescriptions.get(1)); List testDescriptions = containerDescriptions.get(0).getChildren(); assertEquals(testDescription("[root:test1]"), getOnlyElement(testDescriptions)); testDescriptions = containerDescriptions.get(1).getChildren(); assertThat(testDescriptions).hasSize(2); assertEquals(testDescription("[root:test2a]"), testDescriptions.get(0)); assertEquals(testDescription("[root:test2b]"), testDescriptions.get(1)); } private static void assertIncludes(Filter filter, T included) { assertThat(filter.apply(included).included()).isTrue(); } private static void assertExcludes(Filter filter, T excluded) { assertThat(filter.apply(excluded).excluded()).isTrue(); } } @Nested class Filtering { private final ConfigurationParameters configParams = mock(); @Test void appliesFilter() throws Exception { TestDescriptor originalParent1 = new TestDescriptorStub(UniqueId.root("root", "parent1"), "parent1"); originalParent1.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf1"), "leaf1")); TestDescriptor originalParent2 = new TestDescriptorStub(UniqueId.root("root", "parent2"), "parent2"); originalParent2.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2a"), "leaf2a")); originalParent2.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2b"), "leaf2b")); var fullTestPlan = TestPlan.from(List.of(originalParent1, originalParent2), configParams); TestDescriptor filteredParent = new TestDescriptorStub(UniqueId.root("root", "parent2"), "parent2"); filteredParent.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2b"), "leaf2b")); var filteredTestPlan = TestPlan.from(Set.of(filteredParent), configParams); var launcher = mock(Launcher.class); var captor = ArgumentCaptor.forClass(LauncherDiscoveryRequest.class); when(launcher.discover(captor.capture())).thenReturn(fullTestPlan).thenReturn(filteredTestPlan); var runner = new JUnitPlatform(TestClass.class, launcher); runner.filter(matchMethodDescription(testDescription("[root:leaf2b]"))); var lastDiscoveryRequest = captor.getValue(); var uniqueIdSelectors = lastDiscoveryRequest.getSelectorsByType(UniqueIdSelector.class); assertEquals("[root:leaf2b]", getOnlyElement(uniqueIdSelectors).getUniqueId().toString()); var parentDescription = getOnlyElement(runner.getDescription().getChildren()); assertEquals(suiteDescription("[root:parent2]"), parentDescription); var testDescription = getOnlyElement(parentDescription.getChildren()); assertEquals(testDescription("[root:leaf2b]"), testDescription); } @Test void throwsNoTestsRemainExceptionWhenNoTestIdentifierMatchesFilter() { var testPlan = TestPlan.from(Set.of(new TestDescriptorStub(UniqueId.root("root", "test"), "test")), configParams); var launcher = mock(Launcher.class); when(launcher.discover(any())).thenReturn(testPlan); var runner = new JUnitPlatform(TestClass.class, launcher); assertThrows(NoTestsRemainException.class, () -> runner.filter(matchMethodDescription(suiteDescription("[root:doesNotExist]")))); } } @Nested class Execution { @Test void notifiesRunListenerOfTestExecution() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("failingTest", () -> fail("expected to fail")); engine.addTest("succeedingTest", () -> { }); engine.addTest("abortedTest", () -> assumeFalse(true)); engine.addTest("skippedTest", () -> fail("never called")).markSkipped("should be skipped"); var runListener = mock(RunListener.class); var notifier = new RunNotifier(); notifier.addListener(runListener); new JUnitPlatform(TestClass.class, createLauncher(engine)).run(notifier); var inOrder = inOrder(runListener); inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:failingTest]")); inOrder.verify(runListener).testFailure(any()); inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:failingTest]")); inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:succeedingTest]")); inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:succeedingTest]")); inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:abortedTest]")); inOrder.verify(runListener).testAssumptionFailure(any()); inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:abortedTest]")); inOrder.verify(runListener).testIgnored(testDescription("[engine:dummy]/[test:skippedTest]")); inOrder.verifyNoMoreInteractions(); } @Test void supportsDynamicTestRegistration() throws Exception { var runListener = mock(RunListener.class); var notifier = new RunNotifier(); // notifier.addListener(new LoggingRunListener()); notifier.addListener(runListener); new JUnitPlatform(TestClass.class, createLauncher(new DynamicTestEngine())).run(notifier); var inOrder = inOrder(runListener); inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:1]")); inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:1]")); inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:2]")); inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:2]")); inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:3]")); inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:3]")); inOrder.verify(runListener).testStarted( testDescription("[engine:dynamic]/[container:1]/[test:3]/[test:3a]")); inOrder.verify(runListener).testFinished( testDescription("[engine:dynamic]/[container:1]/[test:3]/[test:3a]")); inOrder.verifyNoMoreInteractions(); } @Test void reportsIgnoredEventsForLeavesWhenContainerIsSkipped() throws Exception { var uniqueEngineId = UniqueId.forEngine("engine"); TestDescriptor engineDescriptor = new EngineDescriptor(uniqueEngineId, "engine"); TestDescriptor container = new TestDescriptorStub(UniqueId.root("root", "container"), "container"); container.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf"), "leaf")); engineDescriptor.addChild(container); var engine = mock(TestEngine.class); when(engine.getId()).thenReturn("engine"); when(engine.discover(any(), eq(uniqueEngineId))).thenReturn(engineDescriptor); doAnswer(invocation -> { ExecutionRequest request = invocation.getArgument(0); var listener = request.getEngineExecutionListener(); listener.executionStarted(engineDescriptor); listener.executionSkipped(container, "deliberately skipped container"); listener.executionFinished(engineDescriptor, successful()); return null; }).when(engine).execute(any()); var runListener = mock(RunListener.class); var notifier = new RunNotifier(); notifier.addListener(runListener); new JUnitPlatform(TestClass.class, createLauncher(engine)).run(notifier); verify(runListener).testIgnored(testDescription("[root:leaf]")); verifyNoMoreInteractions(runListener); } } @Nested class Descriptions { @Test @DisplayName("Suite with default display name") void descriptionForTestSuiteWithDefaultDisplayName() { Class testClass = TestSuiteWithDefaultDisplayName.class; var platformRunner = new JUnitPlatform(testClass, createLauncher(new DemoHierarchicalTestEngine("suite names"))); assertEquals(testClass.getName(), platformRunner.getDescription().getDisplayName()); } @Test @DisplayName("Suite with @SuiteDisplayName") void descriptionForTestSuiteWithCustomDisplayName() { var platformRunner = new JUnitPlatform(TestSuiteWithCustomDisplayName.class, createLauncher(new DemoHierarchicalTestEngine("suite names"))); assertEquals("Sweeeeeeet Name!", platformRunner.getDescription().getDisplayName()); } @Test @DisplayName("Suite with @SuiteDisplayName and @UseTechnicalNames") void descriptionForTestSuiteWithCustomDisplayNameAndTechnicalNames() { Class testClass = TestSuiteWithCustomDisplayNameAndTechnicalNames.class; var platformRunner = new JUnitPlatform(testClass, createLauncher(new DemoHierarchicalTestEngine("suite names"))); assertEquals(testClass.getName(), platformRunner.getDescription().getDisplayName()); } @Test void descriptionForJavaMethodAndClassSources() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); var failingTest = getClass().getDeclaredMethod("failingTest"); var containerDescriptor = engine.addContainer("uniqueContainerName", "containerDisplayName", ClassSource.from(getClass())); containerDescriptor.addChild( new DemoHierarchicalTestDescriptor(containerDescriptor.getUniqueId().append("test", "failingTest"), "testDisplayName", MethodSource.from(failingTest), (c, t) -> { })); var platformRunner = new JUnitPlatform(TestClass.class, createLauncher(engine)); List children = platformRunner.getDescription().getChildren(); assertEquals(1, children.size()); var engineDescription = children.get(0); assertEquals("dummy", engineDescription.getDisplayName()); var containerDescription = getOnlyElement(engineDescription.getChildren()); var testDescription = getOnlyElement(containerDescription.getChildren()); // @formatter:off assertAll( () -> assertEquals("dummy", engineDescription.getDisplayName(), "engine display name"), () -> assertEquals("dummy", engineDescription.getClassName(), "engine class name"), () -> assertNull(engineDescription.getMethodName(), "engine method name"), () -> assertEquals("containerDisplayName", containerDescription.getDisplayName(), "container display name"), () -> assertEquals("containerDisplayName", containerDescription.getClassName(), "container class name"), () -> assertNull(containerDescription.getMethodName(), "container method name"), () -> assertEquals("testDisplayName(containerDisplayName)", testDescription.getDisplayName(), "test display name"), () -> assertEquals("containerDisplayName", testDescription.getClassName(), "test class name"), () -> assertEquals("testDisplayName", testDescription.getMethodName(), "test method name") ); // @formatter:on } @Test void descriptionForJavaMethodAndClassSourcesUsingTechnicalNames() throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); var failingTest = getClass().getDeclaredMethod("failingTest"); var containerDescriptor = engine.addContainer("uniqueContainerName", "containerDisplayName", ClassSource.from(getClass())); containerDescriptor.addChild( new DemoHierarchicalTestDescriptor(containerDescriptor.getUniqueId().append("test", "failingTest"), "testDisplayName", MethodSource.from(failingTest), (c, t) -> { })); var platformRunner = new JUnitPlatform(TestClassWithTechnicalNames.class, createLauncher(engine)); List children = platformRunner.getDescription().getChildren(); assertEquals(1, children.size()); var engineDescription = children.get(0); assertEquals("dummy", engineDescription.getDisplayName()); var containerDescription = getOnlyElement(engineDescription.getChildren()); var testDescription = getOnlyElement(containerDescription.getChildren()); // @formatter:off assertAll( () -> assertEquals("dummy", engineDescription.getDisplayName(), "engine display name"), () -> assertEquals("dummy", engineDescription.getClassName(), "engine class name"), () -> assertNull(engineDescription.getMethodName(), "engine method name"), () -> assertEquals(getClass().getName(), containerDescription.getDisplayName(), "container display name"), () -> assertEquals(getClass().getName(), containerDescription.getClassName(), "container class name"), () -> assertNull(containerDescription.getMethodName(), "container method name"), () -> assertEquals("failingTest(" + getClass().getName() + ")", testDescription.getDisplayName(), "test display name"), () -> assertEquals(getClass().getName(), testDescription.getClassName(), "test class name"), () -> assertEquals("failingTest", testDescription.getMethodName(), "test method name") ); // @formatter:on } void failingTest() { // not actually invoked } } // ------------------------------------------------------------------------- private static Description suiteDescription(String uniqueId) { return createSuiteDescription(uniqueId, UniqueId.parse(uniqueId)); } private static Description testDescription(String uniqueId) { return createTestDescription(uniqueId, uniqueId, UniqueId.parse(uniqueId)); } private TestDescriptor testDescriptorWithTags(String... tag) { var testDescriptor = mock(TestDescriptor.class); var tags = Arrays.stream(tag).map(TestTag::create).collect(toSet()); when(testDescriptor.getTags()).thenReturn(tags); return testDescriptor; } private LauncherDiscoveryRequest instantiateRunnerAndCaptureGeneratedRequest(Class testClass) { var launcher = mock(Launcher.class); var captor = ArgumentCaptor.forClass(LauncherDiscoveryRequest.class); when(launcher.discover(captor.capture())).thenReturn(TestPlan.from(Set.of(), mock())); new JUnitPlatform(testClass, launcher); return captor.getValue(); } private static class TestClass { } @UseTechnicalNames private static class TestClassWithTechnicalNames { } private static class TestSuiteWithDefaultDisplayName { } @SuiteDisplayName("Sweeeeeeet Name!") private static class TestSuiteWithCustomDisplayName { } @SuiteDisplayName("Sweeeeeeet Name!") @UseTechnicalNames private static class TestSuiteWithCustomDisplayNameAndTechnicalNames { } private static class DynamicTestEngine implements TestEngine { @Override public String getId() { return "dynamic"; } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { return new EngineDescriptor(uniqueId, "Dynamic Engine"); } @Override public void execute(ExecutionRequest request) { var engineExecutionListener = request.getEngineExecutionListener(); var root = request.getRootTestDescriptor(); TestDescriptor container = new DemoContainerTestDescriptor(root.getUniqueId().append("container", "1"), "container #1"); root.addChild(container); engineExecutionListener.dynamicTestRegistered(container); engineExecutionListener.executionStarted(container); var containerUid = container.getUniqueId(); TestDescriptor dynamicTest1 = new DemoTestTestDescriptor(containerUid.append("test", "1"), "dynamic test #1"); container.addChild(dynamicTest1); engineExecutionListener.dynamicTestRegistered(dynamicTest1); engineExecutionListener.executionStarted(dynamicTest1); engineExecutionListener.executionFinished(dynamicTest1, TestExecutionResult.successful()); TestDescriptor dynamicTest2 = new DemoTestTestDescriptor(containerUid.append("test", "2"), "dynamic test #2"); container.addChild(dynamicTest2); engineExecutionListener.dynamicTestRegistered(dynamicTest2); engineExecutionListener.executionStarted(dynamicTest2); engineExecutionListener.executionFinished(dynamicTest2, TestExecutionResult.successful()); TestDescriptor dynamicTest3 = new DemoContainerAndTestTestDescriptor(containerUid.append("test", "3"), "dynamic test #3"); container.addChild(dynamicTest3); engineExecutionListener.dynamicTestRegistered(dynamicTest3); engineExecutionListener.executionStarted(dynamicTest3); engineExecutionListener.executionFinished(dynamicTest3, TestExecutionResult.successful()); TestDescriptor dynamicTest3a = new DemoTestTestDescriptor(dynamicTest3.getUniqueId().append("test", "3a"), "dynamic test #3a"); dynamicTest3.addChild(dynamicTest3a); engineExecutionListener.dynamicTestRegistered(dynamicTest3a); engineExecutionListener.executionStarted(dynamicTest3a); engineExecutionListener.executionFinished(dynamicTest3a, TestExecutionResult.successful()); engineExecutionListener.executionFinished(container, TestExecutionResult.successful()); } } private static class DemoContainerTestDescriptor extends AbstractTestDescriptor { DemoContainerTestDescriptor(UniqueId uniqueId, String displayName) { super(uniqueId, displayName); } @Override public Type getType() { return Type.CONTAINER; } } private static class DemoTestTestDescriptor extends AbstractTestDescriptor { DemoTestTestDescriptor(UniqueId uniqueId, String displayName) { super(uniqueId, displayName); } @Override public Type getType() { return Type.TEST; } } private static class DemoContainerAndTestTestDescriptor extends AbstractTestDescriptor { DemoContainerAndTestTestDescriptor(UniqueId uniqueId, String displayName) { super(uniqueId, displayName); } @Override public Type getType() { return Type.CONTAINER_AND_TEST; } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/000077500000000000000000000000001455764576500255775ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/commons/000077500000000000000000000000001455764576500272525ustar00rootroot00000000000000SuiteLauncherDiscoveryRequestBuilderTests.java000066400000000000000000000534561455764576500404210ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/commons/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.commons; import static java.util.Map.entry; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder.request; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.URI; import java.nio.file.Paths; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.FilePosition; import org.junit.platform.engine.discovery.FileSelector; import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.engine.discovery.PackageSelector; import org.junit.platform.engine.discovery.UriSelector; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.launcher.EngineFilter; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.DisableParentConfigurationParameters; import org.junit.platform.suite.api.ExcludeClassNamePatterns; import org.junit.platform.suite.api.ExcludeEngines; import org.junit.platform.suite.api.ExcludePackages; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.IncludePackages; import org.junit.platform.suite.api.IncludeTags; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.SelectClasspathResource; import org.junit.platform.suite.api.SelectDirectories; import org.junit.platform.suite.api.SelectFile; import org.junit.platform.suite.api.SelectMethod; import org.junit.platform.suite.api.SelectModules; import org.junit.platform.suite.api.SelectPackages; import org.junit.platform.suite.api.SelectUris; class SuiteLauncherDiscoveryRequestBuilderTests { SuiteLauncherDiscoveryRequestBuilder builder = request(); @Test void configurationParameter() { @ConfigurationParameter(key = "com.example", value = "*") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); ConfigurationParameters configuration = request.getConfigurationParameters(); Optional parameter = configuration.get("com.example"); assertEquals(Optional.of("*"), parameter); } @Test void excludeClassNamePatterns() { class TestCase { } @ExcludeClassNamePatterns("^.*TestCase$") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getFiltersByType(ClassNameFilter.class); assertTrue(exactlyOne(filters).apply(TestCase.class.getName()).excluded()); } @Test void excludeEngines() { @ExcludeEngines("junit-jupiter") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getEngineFilters(); assertTrue(exactlyOne(filters).apply(new JupiterTestEngine()).excluded()); } @Test void excludePackages() { @ExcludePackages("com.example.testcases") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getFiltersByType(PackageNameFilter.class); assertTrue(exactlyOne(filters).apply("com.example.testcases").excluded()); } @Test void excludeTags() { @ExcludeTags("test-tag") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getPostDiscoveryFilters(); TestDescriptor testDescriptor = new StubAbstractTestDescriptor(); assertTrue(exactlyOne(filters).apply(testDescriptor).excluded()); } @Test void includeClassNamePatterns() { class TestCase { } @IncludeClassNamePatterns("^.*TestCase$") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getFiltersByType(ClassNameFilter.class); assertTrue(exactlyOne(filters).apply(TestCase.class.getName()).included()); assertTrue(exactlyOne(filters).apply(Suite.class.getName()).excluded()); } @Test void filtersOnStandardClassNamePatternsWhenIncludeClassNamePatternsIsOmitted() { class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); assertTrue(request.getFiltersByType(ClassNameFilter.class).isEmpty()); } @Test void filtersOnStandardClassNamePatternsWhenIncludeClassNamePatternsIsOmittedUnlessDisabled() { class ExampleTest { } class Suite { } // @formatter:off LauncherDiscoveryRequest request = builder .filterStandardClassNamePatterns(true) .suite(Suite.class) .build(); // @formatter:on List filters = request.getFiltersByType(ClassNameFilter.class); assertTrue(exactlyOne(filters).apply(ExampleTest.class.getName()).included()); assertTrue(exactlyOne(filters).apply(Suite.class.getName()).excluded()); } @Test void includeEngines() { @IncludeEngines("junit-jupiter") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getEngineFilters(); assertTrue(exactlyOne(filters).apply(new JupiterTestEngine()).included()); } @Test void includePackages() { @IncludePackages("com.example.testcases") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getFiltersByType(PackageNameFilter.class); assertTrue(exactlyOne(filters).apply("com.example.testcases").included()); } @Test void includeTags() { @IncludeTags("test-tag") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List filters = request.getPostDiscoveryFilters(); TestDescriptor testDescriptor = new StubAbstractTestDescriptor(); assertTrue(exactlyOne(filters).apply(testDescriptor).included()); } @Test void selectClassesByReference() { class TestCase { } @SelectClasses(TestCase.class) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ClassSelector.class); assertFalse(selectors.isEmpty()); assertEquals(TestCase.class, exactlyOne(selectors).getJavaClass()); } @Test void selectClassesByName() { @SelectClasses(names = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$NonLocalTestCase") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ClassSelector.class); assertEquals(NonLocalTestCase.class, exactlyOne(selectors).getJavaClass()); } @Test void selectClassesWithoutReferencesOrNames() { @SelectClasses class Suite { } var e = assertThrows(PreconditionViolationException.class, () -> builder.suite(Suite.class)); assertThat(e).hasMessageMatching( "@SelectClasses on class \\[" + Pattern.quote(SuiteLauncherDiscoveryRequestBuilderTests.class.getName()) + "\\$\\d+Suite] must declare at least one class reference or name"); } static class NonLocalTestCase { } @TestFactory Stream selectOneMethodWithNoParameters() { @SelectMethod("org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$NoParameterTestCase#testMethod") class SuiteA { } @SelectMethod(type = NoParameterTestCase.class, name = "testMethod") class SuiteB { } @SelectMethod(typeName = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$NoParameterTestCase", name = "testMethod") class SuiteC { } return Stream.of(SuiteA.class, SuiteB.class, SuiteC.class) // .map(suiteClass -> dynamicTest(suiteClass.getSimpleName(), () -> { LauncherDiscoveryRequest request = request().suite(suiteClass).build(); List selectors = request.getSelectorsByType(MethodSelector.class); assertEquals(DiscoverySelectors.selectMethod(NoParameterTestCase.class, "testMethod"), exactlyOne(selectors)); })); } static class NoParameterTestCase { @SuppressWarnings("unused") void testMethod() { } } @TestFactory Stream selectOneMethodWithOneParameter() { @SelectMethod("org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$OneParameterTestCase#testMethod(int)") class SuiteA { } @SelectMethod(type = OneParameterTestCase.class, name = "testMethod", parameterTypeNames = "int") class SuiteB { } @SelectMethod(type = OneParameterTestCase.class, name = "testMethod", parameterTypes = int.class) class SuiteC { } @SelectMethod(typeName = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$OneParameterTestCase", name = "testMethod", parameterTypeNames = "int") class SuiteD { } @SelectMethod(typeName = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$OneParameterTestCase", name = "testMethod", parameterTypes = int.class) class SuiteE { } return Stream.of(SuiteA.class, SuiteB.class, SuiteC.class, SuiteD.class, SuiteE.class) // .map(suiteClass -> dynamicTest(suiteClass.getSimpleName(), () -> { LauncherDiscoveryRequest request = request().suite(suiteClass).build(); List selectors = request.getSelectorsByType(MethodSelector.class); assertEquals(DiscoverySelectors.selectMethod(OneParameterTestCase.class, "testMethod", "int"), exactlyOne(selectors)); })); } static class OneParameterTestCase { @SuppressWarnings("unused") void testMethod(int i) { } } @Test void selectTwoMethodsWithTwoParameters() { @SuppressWarnings("unused") class TestClass { void firstTestMethod(int i, String j) { } void secondTestMethod(boolean i, float j) { } } @SelectMethod(type = TestClass.class, name = "firstTestMethod", parameterTypeNames = "int, java.lang.String") @SelectMethod(type = TestClass.class, name = "secondTestMethod", parameterTypes = { boolean.class, float.class }) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(MethodSelector.class); assertEquals(2, selectors.size()); assertEquals(DiscoverySelectors.selectMethod(TestClass.class, "firstTestMethod", "int, java.lang.String"), selectors.get(0)); assertEquals(DiscoverySelectors.selectMethod(TestClass.class, "secondTestMethod", "boolean, float"), selectors.get(1)); } @TestFactory Stream selectMethodCausesExceptionOnInvalidUsage() { @SelectMethod(value = "irrelevant", type = NoParameterTestCase.class) class ValueAndType { } @SelectMethod(value = "SomeClass#someMethod", typeName = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$NoParameterTestCase") class ValueAndTypeName { } @SelectMethod(value = "SomeClass#someMethod", name = "testMethod") class ValueAndMethodName { } @SelectMethod(value = "SomeClass#someMethod", parameterTypes = int.class) class ValueAndParameterTypes { } @SelectMethod(value = "SomeClass#someMethod", parameterTypeNames = "int") class ValueAndParameterTypeNames { } @SelectMethod(type = NoParameterTestCase.class) class MissingMethodName { } @SelectMethod(name = "testMethod", type = NoParameterTestCase.class, typeName = "org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilderTests$NoParameterTestCase") class TypeAndTypeName { } @SelectMethod(name = "testMethod", parameterTypes = int.class, parameterTypeNames = "int") class ParameterTypesAndParameterTypeNames { } var expectedFailureMessages = Map.ofEntries( // entry(ValueAndType.class, "type must not be set in conjunction with fully qualified method name"), // entry(ValueAndTypeName.class, "type name must not be set in conjunction with fully qualified method name"), // entry(ValueAndMethodName.class, "method name must not be set in conjunction with fully qualified method name"), // entry(ValueAndParameterTypes.class, "parameter types must not be set in conjunction with fully qualified method name"), // entry(ValueAndParameterTypeNames.class, "parameter type names must not be set in conjunction with fully qualified method name"), // entry(MissingMethodName.class, "method name must not be blank"), // entry(TypeAndTypeName.class, "either type name or type must be set but not both"), // entry(ParameterTypesAndParameterTypeNames.class, "either parameter type names or parameter types must be set but not both") // ); return expectedFailureMessages.entrySet().stream() // .map(entry -> { Class suiteClassName = entry.getKey(); var expectedFailureMessage = entry.getValue(); return dynamicTest(suiteClassName.getSimpleName(), () -> { var ex = assertThrows(PreconditionViolationException.class, () -> request().suite(suiteClassName)); assertEquals( "@SelectMethod on class [" + suiteClassName.getName() + "]: " + expectedFailureMessage, ex.getMessage()); }); }); } @Test void selectClasspathResource() { @SelectClasspathResource("com.example.testcases") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ClasspathResourceSelector.class); assertEquals("com.example.testcases", exactlyOne(selectors).getClasspathResourceName()); } @Test void selectClasspathResourcePosition() { @SelectClasspathResource(value = "com.example.testcases", line = 42) @SelectClasspathResource(value = "com.example.testcases", line = 14, column = 15) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ClasspathResourceSelector.class); assertEquals(Optional.of(FilePosition.from(42)), selectors.get(0).getPosition()); assertEquals(Optional.of(FilePosition.from(14, 15)), selectors.get(1).getPosition()); } @Test void ignoreClasspathResourcePosition() { @SelectClasspathResource(value = "com.example.testcases", line = -1) @SelectClasspathResource(value = "com.example.testcases", column = 12) @SelectClasspathResource(value = "com.example.testcases", line = 42, column = -12) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ClasspathResourceSelector.class); assertEquals(Optional.empty(), selectors.get(0).getPosition()); assertEquals(Optional.empty(), selectors.get(1).getPosition()); assertEquals(Optional.of(FilePosition.from(42)), selectors.get(2).getPosition()); } @Test void selectDirectories() { @SelectDirectories("path/to/root") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(DirectorySelector.class); assertEquals(Paths.get("path/to/root"), exactlyOne(selectors).getPath()); } @Test void selectDirectoriesFiltersEmptyPaths() { @SelectDirectories("") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); assertTrue(request.getSelectorsByType(DirectorySelector.class).isEmpty()); } @Test void selectFile() { @SelectFile("path/to/root") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(FileSelector.class); assertEquals(Paths.get("path/to/root"), exactlyOne(selectors).getPath()); } @Test void selectFilePosition() { @SelectFile(value = "path/to/root", line = 42) @SelectFile(value = "path/to/root", line = 14, column = 15) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(FileSelector.class); assertEquals(Optional.of(FilePosition.from(42)), selectors.get(0).getPosition()); assertEquals(Optional.of(FilePosition.from(14, 15)), selectors.get(1).getPosition()); } @Test void ignoreInvalidFilePosition() { @SelectFile(value = "path/to/root", line = -1) @SelectFile(value = "path/to/root", column = 12) @SelectFile(value = "path/to/root", line = 42, column = -12) class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(FileSelector.class); assertEquals(Optional.empty(), selectors.get(0).getPosition()); assertEquals(Optional.empty(), selectors.get(1).getPosition()); assertEquals(Optional.of(FilePosition.from(42)), selectors.get(2).getPosition()); } @Test void selectModules() { @SelectModules("com.example.testcases") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(ModuleSelector.class); assertEquals("com.example.testcases", exactlyOne(selectors).getModuleName()); } @Test void selectUris() { @SelectUris("path/to/root") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(UriSelector.class); assertEquals(URI.create("path/to/root"), exactlyOne(selectors).getUri()); } @Test void selectUrisFiltersEmptyUris() { @SelectUris("") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); assertTrue(request.getSelectorsByType(UriSelector.class).isEmpty()); } @Test void selectPackages() { @SelectPackages("com.example.testcases") class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List selectors = request.getSelectorsByType(PackageSelector.class); assertEquals("com.example.testcases", exactlyOne(selectors).getPackageName()); } @SelectPackages("com.example.testcases") @Retention(RetentionPolicy.RUNTIME) @interface Meta { } @Test void metaAnnotations() { @Meta class Suite { } LauncherDiscoveryRequest request = builder.suite(Suite.class).build(); List pSelectors = request.getSelectorsByType(PackageSelector.class); assertEquals("com.example.testcases", exactlyOne(pSelectors).getPackageName()); } @Test void enableParentConfigurationParametersByDefault() { class Suite { } // @formatter:off var configuration = new ParentConfigurationParameters("parent", "parent parameters were used"); var request = builder.suite(Suite.class) .parentConfigurationParameters(configuration) .build(); // @formatter:on var configurationParameters = request.getConfigurationParameters(); assertEquals(Optional.of("parent parameters were used"), configurationParameters.get("parent")); } @Test void disableParentConfigurationParameters() { @DisableParentConfigurationParameters class Suite { } // @formatter:off var configuration = new ParentConfigurationParameters("parent", "parent parameters were used"); var request = builder.suite(Suite.class) .parentConfigurationParameters(configuration) .build(); // @formatter:on var configurationParameters = request.getConfigurationParameters(); assertEquals(Optional.empty(), configurationParameters.get("parent")); } private static T exactlyOne(List list) { return CollectionUtils.getOnlyElement(list); } private static class StubAbstractTestDescriptor extends AbstractTestDescriptor { public StubAbstractTestDescriptor() { super(UniqueId.forEngine("test"), "stub"); } @Override public Type getType() { return Type.CONTAINER; } @Override public Set getTags() { return Collections.singleton(TestTag.create("test-tag")); } } private static class ParentConfigurationParameters implements ConfigurationParameters { private final Map map; public ParentConfigurationParameters(String key, String value) { this.map = Map.of(key, value); } @Override public Optional get(String key) { return Optional.ofNullable(map.get(key)); } @Override public Optional getBoolean(String key) { return Optional.empty(); } @Override @SuppressWarnings("deprecation") public int size() { return map.size(); } @Override public Set keySet() { return null; } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/000077500000000000000000000000001455764576500270445ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java000066400000000000000000000336621455764576500331630ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.TagFilter.excludeTags; import static org.junit.platform.suite.engine.SuiteEngineDescriptor.ENGINE_ID; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.PostDiscoveryFilter; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.DynamicTestsTestCase; import org.junit.platform.suite.engine.testcases.JUnit4TestsTestCase; import org.junit.platform.suite.engine.testcases.MultipleTestsTestCase; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; import org.junit.platform.suite.engine.testcases.TaggedTestTestCase; import org.junit.platform.suite.engine.testsuites.AbstractSuite; import org.junit.platform.suite.engine.testsuites.CyclicSuite; import org.junit.platform.suite.engine.testsuites.DynamicSuite; import org.junit.platform.suite.engine.testsuites.EmptyCyclicSuite; import org.junit.platform.suite.engine.testsuites.EmptyDynamicTestSuite; import org.junit.platform.suite.engine.testsuites.EmptyDynamicTestWithFailIfNoTestFalseSuite; import org.junit.platform.suite.engine.testsuites.EmptyTestCaseSuite; import org.junit.platform.suite.engine.testsuites.EmptyTestCaseWithFailIfNoTestFalseSuite; import org.junit.platform.suite.engine.testsuites.MultiEngineSuite; import org.junit.platform.suite.engine.testsuites.MultipleSuite; import org.junit.platform.suite.engine.testsuites.NestedSuite; import org.junit.platform.suite.engine.testsuites.SelectClassesSuite; import org.junit.platform.suite.engine.testsuites.SelectMethodsSuite; import org.junit.platform.suite.engine.testsuites.SuiteDisplayNameSuite; import org.junit.platform.suite.engine.testsuites.SuiteSuite; import org.junit.platform.suite.engine.testsuites.ThreePartCyclicSuite; import org.junit.platform.testkit.engine.EngineTestKit; /** * @since 1.8 */ class SuiteEngineTests { @Test void selectClasses() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(SelectClassesSuite.class)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(SelectClassesSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectMethods() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(SelectMethodsSuite.class)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(MultipleTestsTestCase.class.getName(), "test()"), finishedSuccessfully())) .doNotHave(event(test(MultipleTestsTestCase.class.getName(), "test2()"))); // @formatter:on } @Test void suiteDisplayName() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(SuiteDisplayNameSuite.class)) .execute() .allEvents() .assertThatEvents() .haveExactly(1, event(container(displayName("Suite Display Name")), finishedSuccessfully())); // @formatter:on } @Test void abstractSuiteIsNotExecuted() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(AbstractSuite.class)) .execute() .testEvents() .assertThatEvents() .isEmpty(); // @formatter:on } @Test void privateSuiteIsNotExecuted() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(PrivateSuite.class)) .execute() .testEvents() .assertThatEvents() .isEmpty(); // @formatter:on } @Suite @SelectClasses(SingleTestTestCase.class) private static class PrivateSuite { } @Test void innerSuiteIsNotExecuted() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(InnerSuite.class)) .execute() .testEvents() .assertThatEvents() .isEmpty(); // @formatter:on } @SuppressWarnings("InnerClassMayBeStatic") @Suite @SelectClasses(names = "org.junit.platform.suite.engine.testcases.SingleTestTestCase") private class InnerSuite { } @Test void nestedSuiteIsNotExecuted() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(NestedSuite.class)) .execute() .testEvents() .assertThatEvents() .isEmpty(); // @formatter:on } @Test void dynamicSuite() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(DynamicSuite.class)) .execute() .testEvents() .assertThatEvents() .haveExactly(2, event(test(DynamicTestsTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void suiteSuite() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(SuiteSuite.class)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(SuiteSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(SelectClassesSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectClassesByUniqueId() { // @formatter:off UniqueId uniqId = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, SelectClassesSuite.class.getName()); EngineTestKit.engine(ENGINE_ID) .selectors(selectUniqueId(uniqId)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(SelectClassesSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectMethodInTestPlanByUniqueId() { // @formatter:off UniqueId uniqueId = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, MultipleSuite.class.getName()) .append("engine", JupiterEngineDescriptor.ENGINE_ID) .append(ClassTestDescriptor.SEGMENT_TYPE, MultipleTestsTestCase.class.getName()) .append(TestMethodTestDescriptor.SEGMENT_TYPE, "test()"); EngineTestKit.engine(ENGINE_ID) .selectors(selectUniqueId(uniqueId)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(MultipleSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(MultipleTestsTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectSuiteByUniqueId() { // @formatter:off UniqueId uniqueId = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, MultipleSuite.class.getName()); EngineTestKit.engine(ENGINE_ID) .selectors(selectUniqueId(uniqueId)) .execute() .testEvents() .assertThatEvents() .haveExactly(2, event(test(MultipleSuite.class.getName()), finishedSuccessfully())) .haveExactly(2, event(test(MultipleTestsTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectMethodAndSuiteInTestPlanByUniqueId() { // @formatter:off UniqueId uniqueId = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, MultipleSuite.class.getName()) .append("engine", JupiterEngineDescriptor.ENGINE_ID) .append(ClassTestDescriptor.SEGMENT_TYPE, MultipleTestsTestCase.class.getName()) .append(TestMethodTestDescriptor.SEGMENT_TYPE, "test()"); EngineTestKit.engine(ENGINE_ID) .selectors(selectUniqueId(uniqueId)) .selectors(selectClass(SelectClassesSuite.class)) .execute() .testEvents() .assertThatEvents() .haveExactly(1, event(test(SelectClassesSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(MultipleSuite.class.getName()), finishedSuccessfully())) .haveExactly(1, event(test(MultipleTestsTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void selectMethodsInTestPlanByUniqueId() { // @formatter:off UniqueId uniqueId = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, MultipleSuite.class.getName()) .append("engine", JupiterEngineDescriptor.ENGINE_ID) .append(ClassTestDescriptor.SEGMENT_TYPE, MultipleTestsTestCase.class.getName()) .append(TestMethodTestDescriptor.SEGMENT_TYPE, "test()"); UniqueId uniqueId2 = UniqueId.forEngine(ENGINE_ID) .append(SuiteTestDescriptor.SEGMENT_TYPE, MultipleSuite.class.getName()) .append("engine", JupiterEngineDescriptor.ENGINE_ID) .append(ClassTestDescriptor.SEGMENT_TYPE, MultipleTestsTestCase.class.getName()) .append(TestMethodTestDescriptor.SEGMENT_TYPE, "test2()"); EngineTestKit.engine(ENGINE_ID) .selectors(selectUniqueId(uniqueId)) .selectors(selectUniqueId(uniqueId2)) .execute() .testEvents() .assertThatEvents() .haveExactly(2, event(test(MultipleSuite.class.getName()), finishedSuccessfully())) .haveExactly(2, event(test(MultipleTestsTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void postDiscoveryCanRemoveTestDescriptorsInSuite() { // @formatter:off PostDiscoveryFilter postDiscoveryFilter = testDescriptor -> testDescriptor.getSource() .filter(MethodSource.class::isInstance) .map(MethodSource.class::cast) .filter(classSource -> SingleTestTestCase.class.equals(classSource.getJavaClass())) .map(classSource -> FilterResult.excluded("Was a test in SimpleTest")) .orElseGet(() -> FilterResult.included("Was not a test in SimpleTest")); EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(SelectClassesSuite.class)) .filters(postDiscoveryFilter) .execute() .testEvents() .assertThatEvents() .isEmpty(); // @formatter:on } @Test void emptySuiteFails() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(EmptyTestCaseSuite.class)) .execute() .containerEvents() .assertThatEvents() .haveExactly(1, event(container(EmptyTestCaseSuite.class), finishedWithFailure(instanceOf(NoTestsDiscoveredException.class)))); // @formatter:on } @Test void emptySuitePassesWhenFailIfNoTestIsFalse() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(EmptyTestCaseWithFailIfNoTestFalseSuite.class)) .execute() .containerEvents() .assertThatEvents() .haveExactly(1, event(engine(), finishedSuccessfully())); // @formatter:on } @Test void emptyDynamicSuiteFails() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(EmptyDynamicTestSuite.class)) .execute() .containerEvents() .assertThatEvents() .haveExactly(1, event(container(EmptyDynamicTestSuite.class), finishedWithFailure(instanceOf(NoTestsDiscoveredException.class)))); // @formatter:on } @Test void emptyDynamicSuitePassesWhenFailIfNoTestIsFalse() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(EmptyDynamicTestWithFailIfNoTestFalseSuite.class)) .execute() .allEvents() .assertThatEvents() .haveAtLeastOne(event(container(EmptyDynamicTestWithFailIfNoTestFalseSuite.class), finishedSuccessfully())); // @formatter:on } @Test void pruneAfterPostDiscoveryFilters() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(MultiEngineSuite.class)) .filters(excludeTags("excluded")) .execute() .allEvents() .assertThatEvents() .haveExactly(1, event(test(JUnit4TestsTestCase.class.getName()), finishedSuccessfully())) .doNotHave(test(TaggedTestTestCase.class.getName())) .doNotHave(container("junit-jupiter")); // @formatter:on } @Test void cyclicSuite() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(CyclicSuite.class)) .execute() .allEvents() .assertThatEvents() .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } @Test void emptyCyclicSuite() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(EmptyCyclicSuite.class)) .execute() .allEvents() .assertThatEvents() .haveExactly(1, event(container(EmptyCyclicSuite.class), finishedWithFailure(message( "Suite [org.junit.platform.suite.engine.testsuites.EmptyCyclicSuite] did not discover any tests" )))); // @formatter:on } @Test void threePartCyclicSuite() { // @formatter:off EngineTestKit.engine(ENGINE_ID) .selectors(selectClass(ThreePartCyclicSuite.PartA.class)) .execute() .allEvents() .assertThatEvents() .haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully())); // @formatter:on } } SuiteTestDescriptorTests.java000066400000000000000000000077501455764576500346540ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine; import static java.util.Collections.emptySet; import static java.util.stream.Collectors.toSet; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collections; import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor; import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; import org.junit.platform.suite.engine.testsuites.SelectClassesSuite; /** * @since 1.8 */ class SuiteTestDescriptorTests { @Suite static class TestSuite { } UniqueId engineId = UniqueId.forEngine(SuiteEngineDescriptor.ENGINE_ID); UniqueId suiteId = engineId.append(SuiteTestDescriptor.SEGMENT_TYPE, "test"); UniqueId jupiterEngineId = suiteId.append("engine", JupiterEngineDescriptor.ENGINE_ID); UniqueId testClassId = jupiterEngineId.append(ClassTestDescriptor.SEGMENT_TYPE, SingleTestTestCase.class.getName()); UniqueId methodId = testClassId.append(TestMethodTestDescriptor.SEGMENT_TYPE, "test()"); ConfigurationParameters configurationParameters = new EmptyConfigurationParameters(); SuiteTestDescriptor suite = new SuiteTestDescriptor(suiteId, TestSuite.class, configurationParameters); @Test void suiteIsEmptyBeforeDiscovery() { suite.addDiscoveryRequestFrom(SelectClassesSuite.class); assertEquals(emptySet(), suite.getChildren()); } @Test void suiteDiscoversTestsFromClass() { suite.addDiscoveryRequestFrom(SelectClassesSuite.class); suite.discover(); assertEquals(Set.of(jupiterEngineId, testClassId, methodId), suite.getDescendants().stream().map(TestDescriptor::getUniqueId).collect(toSet())); } @Test void suitDiscoversTestsFromUniqueId() { suite.addDiscoveryRequestFrom(methodId); suite.discover(); assertEquals(Set.of(jupiterEngineId, testClassId, methodId), suite.getDescendants().stream().map(TestDescriptor::getUniqueId).collect(toSet())); } @Test void discoveryPlanCanNotBeModifiedAfterDiscovery() { suite.addDiscoveryRequestFrom(SelectClassesSuite.class); suite.discover(); assertAll(() -> { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> suite.addDiscoveryRequestFrom(SelectClassesSuite.class)); assertEquals("discovery request can not be modified after discovery", exception.getMessage()); }, () -> { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> suite.addDiscoveryRequestFrom(methodId)); assertEquals("discovery request can not be modified after discovery", exception.getMessage()); }); } @Test void suiteMayRegisterTests() { assertTrue(suite.mayRegisterTests()); } private static class EmptyConfigurationParameters implements ConfigurationParameters { @Override public Optional get(String key) { return Optional.empty(); } @Override public Optional getBoolean(String key) { return Optional.empty(); } @Override @SuppressWarnings("deprecation") public int size() { return 0; } @Override public Set keySet() { return Collections.emptySet(); } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/000077500000000000000000000000001455764576500310425ustar00rootroot00000000000000DynamicTestsTestCase.java000066400000000000000000000016131455764576500356720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; /** * @since 1.8 */ public class DynamicTestsTestCase { @TestFactory Stream dynamicTests() { return Stream.of(// dynamicTest("Add test", () -> assertEquals(2, Math.addExact(1, 1))), dynamicTest("Multiply Test", () -> assertEquals(4, Math.multiplyExact(2, 2)))// ); } } EmptyDynamicTestsTestCase.java000066400000000000000000000011701455764576500367070ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; /** * @since 1.9 */ public class EmptyDynamicTestsTestCase { @TestFactory Stream dynamicTests() { return Stream.empty(); } } EmptyTestTestCase.java000066400000000000000000000006511455764576500352220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; /** * @since 1.9 */ public class EmptyTestTestCase { } JUnit4TestsTestCase.java000066400000000000000000000007161455764576500354260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import org.junit.Test; public class JUnit4TestsTestCase { @Test public void aTest() { } } MultipleTestsTestCase.java000066400000000000000000000010051455764576500360740ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import org.junit.jupiter.api.Test; /** * @since 1.8 */ public class MultipleTestsTestCase { @Test void test() { } @Test void test2() { } } SingleTestTestCase.java000066400000000000000000000007471455764576500353530ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import org.junit.jupiter.api.Test; /** * @since 1.8 */ public class SingleTestTestCase { @Test void test() { } } TaggedTestTestCase.java000066400000000000000000000010141455764576500353110ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testcases/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testcases; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; public class TaggedTestTestCase { @Test @Tag("excluded") public void test() { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/000077500000000000000000000000001455764576500312605ustar00rootroot00000000000000AbstractSuite.java000066400000000000000000000012021455764576500346140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.8 */ @Suite @SelectClasses(SingleTestTestCase.class) public abstract class AbstractSuite { } CyclicSuite.java000066400000000000000000000013541455764576500342670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.8 */ @Suite @IncludeClassNamePatterns(".*") @SelectClasses({ CyclicSuite.class, SingleTestTestCase.class }) public class CyclicSuite { } DynamicSuite.java000066400000000000000000000011741455764576500344450ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.DynamicTestsTestCase; /** * @since 1.8 */ @Suite @SelectClasses(DynamicTestsTestCase.class) public class DynamicSuite { } EmptyCyclicSuite.java000066400000000000000000000012251455764576500353030ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; /** * @since 1.9.2 */ @Suite @IncludeClassNamePatterns(".*") @SelectClasses(EmptyCyclicSuite.class) public class EmptyCyclicSuite { } EmptyDynamicTestSuite.java000066400000000000000000000012171455764576500363220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.EmptyDynamicTestsTestCase; /** * @since 1.9 */ @Suite @SelectClasses(EmptyDynamicTestsTestCase.class) public class EmptyDynamicTestSuite { } EmptyDynamicTestWithFailIfNoTestFalseSuite.java000066400000000000000000000012731455764576500423430ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.EmptyDynamicTestsTestCase; /** * @since 1.9 */ @Suite(failIfNoTests = false) @SelectClasses(EmptyDynamicTestsTestCase.class) public class EmptyDynamicTestWithFailIfNoTestFalseSuite { } EmptyTestCaseSuite.java000066400000000000000000000011741455764576500356130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.EmptyTestTestCase; /** * @since 1.9 */ @Suite @SelectClasses(EmptyTestTestCase.class) public class EmptyTestCaseSuite { } EmptyTestCaseWithFailIfNoTestFalseSuite.java000066400000000000000000000012501455764576500416250ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.EmptyTestTestCase; /** * @since 1.9 */ @Suite(failIfNoTests = false) @SelectClasses(EmptyTestTestCase.class) public class EmptyTestCaseWithFailIfNoTestFalseSuite { } MultiEngineSuite.java000066400000000000000000000013141455764576500352750ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.JUnit4TestsTestCase; import org.junit.platform.suite.engine.testcases.TaggedTestTestCase; @Suite @SelectClasses({ JUnit4TestsTestCase.class, TaggedTestTestCase.class }) public class MultiEngineSuite { } MultipleSuite.java000066400000000000000000000011771455764576500346570ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.MultipleTestsTestCase; /** * @since 1.8 */ @Suite @SelectClasses(MultipleTestsTestCase.class) public class MultipleSuite { } NestedSuite.java000066400000000000000000000014561455764576500343060ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.MultipleTestsTestCase; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.8 */ public class NestedSuite { @Suite @SelectClasses(SingleTestTestCase.class) static class Jupiter { } @Suite @SelectClasses(MultipleTestsTestCase.class) static class Tagged { } } SelectClassesSuite.java000066400000000000000000000011761455764576500356200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.8 */ @Suite @SelectClasses(SingleTestTestCase.class) public class SelectClassesSuite { } SelectMethodsSuite.java000066400000000000000000000012311455764576500356160ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectMethod; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.MultipleTestsTestCase; /** * @since 1.10 */ @Suite @SelectMethod(type = MultipleTestsTestCase.class, name = "test") public class SelectMethodsSuite { } SuiteDisplayNameSuite.java000066400000000000000000000013371455764576500363020ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.api.SuiteDisplayName; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.8 */ @Suite @SelectClasses(SingleTestTestCase.class) @SuiteDisplayName("Suite Display Name") public class SuiteDisplayNameSuite { } SuiteSuite.java000066400000000000000000000012171455764576500341500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; /** * @since 1.8 */ @Suite @IncludeClassNamePatterns(".*") @SelectClasses(SelectClassesSuite.class) public class SuiteSuite { } ThreePartCyclicSuite.java000066400000000000000000000017561455764576500361140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.suite.engine.testsuites; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; import org.junit.platform.suite.engine.testcases.SingleTestTestCase; /** * @since 1.9.2 */ public class ThreePartCyclicSuite { @Suite @IncludeClassNamePatterns(".*") @SelectClasses({ PartB.class }) public static class PartA { } @Suite @IncludeClassNamePatterns(".*") @SelectClasses({ PartC.class }) public static class PartB { } @Suite @IncludeClassNamePatterns(".*") @SelectClasses({ PartB.class, SingleTestTestCase.class }) public static class PartC { } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/000077500000000000000000000000001455764576500261355ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/engine/000077500000000000000000000000001455764576500274025ustar00rootroot00000000000000EngineTestKitTests.java000066400000000000000000000047121455764576500337320ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import java.util.Optional; import java.util.function.UnaryOperator; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.platform.engine.reporting.ReportEntry; class EngineTestKitTests { private static final String KEY = EngineTestKitTests.class.getName(); @BeforeEach void setSystemProperty() { System.setProperty(KEY, "from system property"); } @AfterEach void resetSystemProperty() { System.clearProperty(KEY); } @Test void ignoresImplicitConfigurationParametersByDefault() { var value = executeExampleTestCaseAndCollectValue(builder -> builder); assertThat(value).isEmpty(); } @ParameterizedTest @CsvSource({ "true, from system property", "false," }) void usesImplicitConfigurationParametersWhenEnabled(boolean enabled, String expectedValue) { var value = executeExampleTestCaseAndCollectValue( builder -> builder.enableImplicitConfigurationParameters(enabled)); assertThat(value).isEqualTo(Optional.ofNullable(expectedValue)); } private Optional executeExampleTestCaseAndCollectValue(UnaryOperator configuration) { return configuration.apply(EngineTestKit.engine("junit-jupiter")) // .selectors(selectClass(ExampleTestCase.class)) // .execute() // .allEvents() // .reportingEntryPublished() // .map(event -> event.getPayload(ReportEntry.class).orElseThrow()) // .map(ReportEntry::getKeyValuePairs) // .map(entries -> entries.get(KEY)) // .findFirst(); } static class ExampleTestCase { @RegisterExtension BeforeEachCallback callback = context -> context.getConfigurationParameter(KEY) // .ifPresent(value -> context.publishReportEntry(KEY, value)); @Test void test() { } } } junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/engine/EventsTests.java000066400000000000000000000244041455764576500325400ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.EventConditions.skippedWithReason; import static org.junit.platform.testkit.engine.EventConditions.started; import java.util.List; import org.assertj.core.error.AssertJMultipleFailuresError; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; import org.opentest4j.AssertionFailedError; class EventsTests { TestDescriptor engineDescriptor = new EngineDescriptor(UniqueId.forEngine("e1"), "engine"); List list = List.of(Event.executionStarted(engineDescriptor), Event.executionSkipped(engineDescriptor, "reason1"), Event.executionSkipped(engineDescriptor, "reason2"), Event.executionFinished(engineDescriptor, TestExecutionResult.successful())); Events events = new Events(list, "test"); @Test @DisplayName("assertEventsMatchExactly: all events in order -> match") void assertEventsMatchExactlyMatchesAllEventsInOrder() { events.assertEventsMatchExactly( // event(engine(), started()), // event(engine(), skippedWithReason("reason1")), // event(engine(), skippedWithReason("reason2")), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLoosely: all events in order -> match") void assertEventsMatchLooselyMatchesAllEventsInOrder() { events.assertEventsMatchLoosely( // event(engine(), started()), // event(engine(), skippedWithReason("reason1")), // event(engine(), skippedWithReason("reason2")), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLoosely: all events in wrong order -> match") void assertEventsMatchLooselyMatchesAllEventsInWrongOrder() { events.assertEventsMatchLoosely( // event(engine(), skippedWithReason("reason2")), // event(engine(), finishedSuccessfully()), // event(engine(), skippedWithReason("reason1")), // event(engine(), started()) // ); } @Test @DisplayName("assertEventsMatchLoosely: tailing subset -> match") void assertEventsMatchLooselyMatchesATailingSubset() { events.assertEventsMatchLoosely( // event(engine(), skippedWithReason("reason1")), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLoosely: starting subset -> match") void assertEventsMatchLooselyMatchesAStartingSubset() { events.assertEventsMatchLoosely( // event(engine(), started()), // event(engine(), skippedWithReason("reason1")) // ); } @Test @DisplayName("assertEventsMatchLoosely: subset in wrong order -> match") void assertEventsMatchLooselyMatchesASubsetInWrongOrder() { events.assertEventsMatchLoosely( // event(engine(), skippedWithReason("reason1")), // event(engine(), started()) // ); } @Test @DisplayName("assertEventsMatchLoosely: only last event -> match") void assertEventsMatchLooselyMatchesTheLastEventAlone() { events.assertEventsMatchLoosely( // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLoosely: only first event -> match") void assertEventsMatchLooselyMatchesTheFirstEventAlone() { events.assertEventsMatchLoosely( // event(engine(), started()) // ); } @Test @DisplayName("assertEventsMatchLoosely: only bad events -> fails") void assertEventsMatchLooselyWithBadConditionsOnlyFails() { Executable willFail = () -> events.assertEventsMatchLoosely( // event(engine(), finishedWithFailure()), // event(engine(), skippedWithReason("other")) // ); var error = assertThrows(AssertJMultipleFailuresError.class, willFail); var failures = error.getFailures(); assertEquals(2, failures.size()); assertEquals(AssertionError.class, failures.get(0).getClass()); assertEquals(AssertionError.class, failures.get(1).getClass()); } @Test @DisplayName("assertEventsMatchLoosely: one matching and one bad event -> fails") void assertEventsMatchLooselyWithOneMatchingAndOneBadConditionFailsPartly() { Executable willFail = () -> events.assertEventsMatchLoosely( // event(engine(), started()), // event(engine(), finishedWithFailure()) // ); var error = assertThrows(AssertJMultipleFailuresError.class, willFail); var failures = error.getFailures(); assertEquals(1, failures.size()); assertEquals(AssertionError.class, failures.get(0).getClass()); } @Test @DisplayName("assertEventsMatchLooselyInOrder: all events in order -> match") void assertEventsMatchLooselyInOrderMatchesAllEventsInOrder() { events.assertEventsMatchLooselyInOrder( // event(engine(), started()), // event(engine(), skippedWithReason("reason1")), // event(engine(), skippedWithReason("reason2")), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: all events in wrong order -> fail") void assertEventsMatchLooselyInOrderWithAllEventsInWrongOrderFails() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), skippedWithReason("reason2")), // event(engine(), finishedSuccessfully()), // event(engine(), skippedWithReason("reason1")), // event(engine(), started()) // ); var error = assertThrows(AssertionFailedError.class, willFail); assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); } @Test @DisplayName("assertEventsMatchLooselyInOrder: tailing subset in order -> match") void assertEventsMatchLooselyInOrderMatchesATailingSubset() { events.assertEventsMatchLooselyInOrder( // event(engine(), skippedWithReason("reason1")), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: starting subset in order -> match") void assertEventsMatchLooselyInOrderMatchesAStartingSubset() { events.assertEventsMatchLooselyInOrder( // event(engine(), started()), // event(engine(), skippedWithReason("reason1")) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: subset in wrong order -> fail") void assertEventsMatchLooselyInOrderWithASubsetInWrongOrderFails() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), skippedWithReason("reason1")), // event(engine(), started()) // ); var error = assertThrows(AssertionFailedError.class, willFail); assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); } @Test @DisplayName("assertEventsMatchLooselyInOrder: last event alone -> match") void assertEventsMatchLooselyInOrderMatchesTheLastEventAlone() { events.assertEventsMatchLooselyInOrder( // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: first event alone -> match") void assertEventsMatchLooselyInOrderMatchesTheFirstEventAlone() { events.assertEventsMatchLooselyInOrder( // event(engine(), started()) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: bad events only -> fail") void assertEventsMatchLooselyInOrderWithBadConditionsOnlyFails() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), finishedWithFailure()), // event(engine(), skippedWithReason("other")) // ); var error = assertThrows(AssertJMultipleFailuresError.class, willFail); var failures = error.getFailures(); assertEquals(2, failures.size()); assertEquals(AssertionError.class, failures.get(0).getClass()); assertEquals(AssertionError.class, failures.get(1).getClass()); } @Test @DisplayName("assertEventsMatchLooselyInOrder: one matching event and one bad event -> fail") void assertEventsMatchLooselyInOrderWithOneMatchingAndOneBadConditionFailsPartly() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), started()), // event(engine(), finishedWithFailure()) // ); var error = assertThrows(AssertJMultipleFailuresError.class, willFail); assertEquals(1, error.getFailures().size()); } @Test @DisplayName("assertEventsMatchLooselyInOrder: first and last event in order -> match") void assertEventsMatchLooselyInOrderMatchesFirstAndLastEventInOrder() { events.assertEventsMatchLooselyInOrder( // event(engine(), started()), // event(engine(), finishedSuccessfully()) // ); } @Test @DisplayName("assertEventsMatchLooselyInOrder: second and last event in bad order -> fail") void assertEventsMatchLooselyInOrderWithSecondAndLastEventInBadOrderFails() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), finishedSuccessfully()), // event(engine(), skippedWithReason("reason1")) // ); var error = assertThrows(AssertionFailedError.class, willFail); assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); } @Test @DisplayName("assertEventsMatchLooselyInOrder: too many events -> fail") void assertEventsMatchLooselyInOrderWithTooManyEventsFails() { Executable willFail = () -> events.assertEventsMatchLooselyInOrder( // event(engine(), finishedSuccessfully()), // event(engine(), finishedSuccessfully()), // event(engine(), finishedSuccessfully()), // event(engine(), finishedSuccessfully()), // event(engine(), finishedSuccessfully()), // event(engine(), finishedSuccessfully())); var error = assertThrows(AssertionError.class, willFail); assertTrue(error.getMessage().endsWith("to be less than or equal to 4 but was 6")); } } ExecutionsIntegrationTests.java000066400000000000000000000072111455764576500355440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Integration tests for {@link Executions}. * * @since 1.4 */ class ExecutionsIntegrationTests { @Test void executionsFromSkippedTestEvents() { var testEvents = getTestEvents(); // We expect 1 for both of the following cases, since an Execution can // be created for a "skipped event even if "started" and "finished" events // are filtered out. assertThat(testEvents.executions().skipped().count()).isEqualTo(1); assertThat(testEvents.skipped().executions().count()).isEqualTo(1); } @Test void executionsFromStartedTestEvents() { var testEvents = getTestEvents(); // We expect 3 if the executions are created BEFORE filtering out "finished" events. assertThat(testEvents.executions().started().count()).isEqualTo(3); // We expect 0 if the executions are created AFTER filtering out "finished" events. assertThat(testEvents.started().executions().count()).isEqualTo(0); } @Test void executionsFromFinishedTestEvents() { var testEvents = getTestEvents(); // We expect 3 if the executions are created BEFORE filtering out "started" events. assertThat(testEvents.executions().finished().count()).isEqualTo(3); // We expect 0 if the executions are created AFTER filtering out "started" events. assertThat(testEvents.finished().executions().count()).isEqualTo(0); } @Test void executionsFromSucceededTestEvents() { var testEvents = getTestEvents(); // We expect 1 if the executions are created BEFORE filtering out "finished" events. assertThat(testEvents.executions().succeeded().count()).isEqualTo(1); // We expect 0 if the executions are created AFTER filtering out "finished" events. assertThat(testEvents.succeeded().executions().count()).isEqualTo(0); } @Test void executionsFromAbortedTestEvents() { var testEvents = getTestEvents(); // We expect 1 if the executions are created BEFORE filtering out "started" events. assertThat(testEvents.executions().aborted().count()).isEqualTo(1); // We expect 0 if the executions are created AFTER filtering out "started" events. assertThat(testEvents.aborted().executions().count()).isEqualTo(0); } @Test void executionsFromFailedTestEvents() { var testEvents = getTestEvents(); // We expect 1 if the executions are created BEFORE filtering out "started" events. assertThat(testEvents.executions().failed().count()).isEqualTo(1); // We expect 0 if the executions are created AFTER filtering out "started" events. assertThat(testEvents.failed().executions().count()).isEqualTo(0); } private Events getTestEvents() { return EngineTestKit.engine("junit-jupiter")// .selectors(selectClass(ExampleTestCase.class))// .execute()// .testEvents()// .assertStatistics(stats -> stats.skipped(1).started(3).succeeded(1).aborted(1).failed(1)); } static class ExampleTestCase { @Test @Disabled void skippedTest() { } @Test void succeedingTest() { } @Test void abortedTest() { assumeTrue(false); } @Test void failingTest() { fail("Boom!"); } } } NestedContainerEventConditionTests.java000066400000000000000000000126351455764576500371560ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/java/org/junit/platform/testkit/engine/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package org.junit.platform.testkit.engine; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.displayName; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.nestedContainer; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.HashMap; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.testkit.engine.NestedContainerEventConditionTests.ATestCase.BTestCase; import org.junit.platform.testkit.engine.NestedContainerEventConditionTests.ATestCase.BTestCase.CTestCase; /** * @since 1.6 */ class NestedContainerEventConditionTests { @Test void preconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> nestedContainer(null))// .withMessage("Class must not be null"); assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(() -> nestedContainer(NestedContainerEventConditionTests.class))// .withMessage(NestedContainerEventConditionTests.class.getName() + " must be a nested class"); } @Test void nestedContainerChecksSuppliedClassAndAllEnclosingClasses() { var uniqueId = UniqueId.root("top-level", getClass().getName())// .append("nested", ATestCase.class.getSimpleName())// .append("nested", BTestCase.class.getSimpleName())// .append("nested", CTestCase.class.getSimpleName()); var event = createEvent(uniqueId); var condition = nestedContainer(HashMap.Entry.class); assertThat(condition.matches(event)).isFalse(); assertThat(condition.toString()).contains(// "is a container", "with uniqueId substring 'Map'", "with uniqueId substring 'Entry'"); condition = nestedContainer(ATestCase.BTestCase.CTestCase.class); assertThat(condition.matches(event)).isTrue(); assertThat(condition.toString()).contains(// "is a container", "with uniqueId substring 'NestedContainerEventConditionTests'", "with uniqueId substring 'ATestCase'", "with uniqueId substring 'BTestCase'", "with uniqueId substring 'CTestCase'"); } private Event createEvent(UniqueId uniqueId) { var testDescriptor = mock(TestDescriptor.class); when(testDescriptor.isContainer()).thenReturn(true); when(testDescriptor.getUniqueId()).thenReturn(uniqueId); var event = mock(Event.class); when(event.getTestDescriptor()).thenReturn(testDescriptor); return event; } @Test void usingNestedContainerCorrectly() { assertDoesNotThrow(() -> container(ATestCase.class)); assertDoesNotThrow(() -> nestedContainer(ATestCase.class)); assertDoesNotThrow(() -> container(ATestCase.BTestCase.class)); assertDoesNotThrow(() -> nestedContainer(ATestCase.BTestCase.class)); assertDoesNotThrow(() -> container(ATestCase.BTestCase.CTestCase.class)); assertDoesNotThrow(() -> nestedContainer(ATestCase.BTestCase.CTestCase.class)); assertDoesNotThrow(() -> container(NestedContainerEventConditionTests.class)); } @Test void eventConditionsForMultipleLevelsOfNestedClasses() { // @formatter:off EngineTestKit.engine("junit-jupiter") .selectors(selectClass(ATestCase.class)) .execute() .allEvents() .assertEventsMatchExactly( event(engine(), started()), event(container(ATestCase.class), started()), event(test("test_a"), started()), event(test("test_a"), finishedSuccessfully()), event(nestedContainer(ATestCase.BTestCase.class, displayName("Test case B")), started()), event(test("test_b"), started()), event(test("test_b"), finishedSuccessfully()), event(nestedContainer(ATestCase.BTestCase.CTestCase.class), started()), event(test("test_c"), started()), event(test("test_c"), finishedSuccessfully()), event(nestedContainer(ATestCase.BTestCase.CTestCase.class), finishedSuccessfully()), event(nestedContainer(ATestCase.BTestCase.class, displayName("Test case B")), finishedSuccessfully()), event(container(ATestCase.class), finishedSuccessfully()), event(engine(), finishedSuccessfully()) ); // @formatter:on } static class ATestCase { @Test void test_a() { } @Nested @DisplayName("Test case B") class BTestCase { @Test void test_b() { } @Nested class CTestCase { @Test void test_c() { } } } } } junit5-r5.10.2/platform-tests/src/test/resources/000077500000000000000000000000001455764576500217735ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/000077500000000000000000000000001455764576500234355ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/000077500000000000000000000000001455764576500250625ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic/000077500000000000000000000000001455764576500261435ustar00rootroot00000000000000Basic-changeDisplayName-flat-ascii.out.txt000066400000000000000000000022551455764576500360440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Started: .oO fancy display name Oo. ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()]) Finished: .oO fancy display name Oo. ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()]) Finished: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-flat-unicode.out.txt000066400000000000000000000022551455764576500364020ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Started: .oO fancy display name Oo. ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()]) Finished: .oO fancy display name Oo. ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()]) Finished: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-none-ascii.out.txt000066400000000000000000000000011455764576500360400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Basic-changeDisplayName-none-unicode.out.txt000066400000000000000000000000011455764576500363760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Basic-changeDisplayName-summary-ascii.out.txt000066400000000000000000000007221455764576500366100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-summary-unicode.out.txt000066400000000000000000000007221455764576500371460ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-testfeed-ascii.out.txt000066400000000000000000000011211455764576500367100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicJUnit Jupiter > Basic > .oO fancy display name Oo. :: STARTED JUnit Jupiter > Basic > .oO fancy display name Oo. :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-testfeed-unicode.out.txt000066400000000000000000000011211455764576500372460ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicJUnit Jupiter > Basic > .oO fancy display name Oo. :: STARTED JUnit Jupiter > Basic > .oO fancy display name Oo. :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-tree-ascii.out.txt000066400000000000000000000010441455764576500360500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic. '-- JUnit Jupiter [OK] '-- Basic [OK] '-- .oO fancy display name Oo. [OK] Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-tree-unicode.out.txt000066400000000000000000000010571455764576500364120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic╷ └─ JUnit Jupiter ✔ └─ Basic ✔ └─ .oO fancy display name Oo. ✔ Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-verbose-ascii.out.txt000066400000000000000000000023051455764576500365570ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Basic | | +-- .oO fancy display name Oo. | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$BasicTestCase', methodName = 'changeDisplayName', methodParameterTypes = ''] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Basic finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-changeDisplayName-verbose-unicode.out.txt000066400000000000000000000024231455764576500371160ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Basic │ │ ├─ .oO fancy display name Oo. │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:changeDisplayName()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$BasicTestCase', methodName = 'changeDisplayName', methodParameterTypes = ''] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Basic finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-flat-ascii.out.txt000066400000000000000000000021571455764576500336270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Started: empty() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()]) Finished: empty() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()]) Finished: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-flat-unicode.out.txt000066400000000000000000000021571455764576500341650ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Started: empty() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()]) Finished: empty() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()]) Finished: Basic ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-none-ascii.out.txt000066400000000000000000000000011455764576500336220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Basic-empty-none-unicode.out.txt000066400000000000000000000000011455764576500341600ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Basic-empty-summary-ascii.out.txt000066400000000000000000000007221455764576500343720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-summary-unicode.out.txt000066400000000000000000000007221455764576500347300ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-testfeed-ascii.out.txt000066400000000000000000000010531455764576500344760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicJUnit Jupiter > Basic > empty() :: STARTED JUnit Jupiter > Basic > empty() :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-testfeed-unicode.out.txt000066400000000000000000000010531455764576500350340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicJUnit Jupiter > Basic > empty() :: STARTED JUnit Jupiter > Basic > empty() :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-tree-ascii.out.txt000066400000000000000000000010211455764576500336250ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic. '-- JUnit Jupiter [OK] '-- Basic [OK] '-- empty() [OK] Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-tree-unicode.out.txt000066400000000000000000000010341455764576500341670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basic╷ └─ JUnit Jupiter ✔ └─ Basic ✔ └─ empty() ✔ Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-verbose-ascii.out.txt000066400000000000000000000022321455764576500343400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Basic | | +-- empty() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$BasicTestCase', methodName = 'empty', methodParameterTypes = ''] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Basic finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Basic-empty-verbose-unicode.out.txt000066400000000000000000000023501455764576500346770ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/basicTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Basic │ │ ├─ empty() │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase]/[method:empty()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$BasicTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$BasicTestCase', methodName = 'empty', methodParameterTypes = ''] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Basic finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail/000077500000000000000000000000001455764576500257755ustar00rootroot00000000000000Fail-failWithMultiLineMessage-flat-ascii.out.txt000066400000000000000000000025161455764576500370530ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Started: failWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()]) Finished: failWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()]) => Exception: org.opentest4j.AssertionFailedError: multi line fail message >> S T A C K T R A C E >> Finished: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-flat-unicode.out.txt000066400000000000000000000025161455764576500374110ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Started: failWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()]) Finished: failWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()]) => Exception: org.opentest4j.AssertionFailedError: multi line fail message >> S T A C K T R A C E >> Finished: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-none-ascii.out.txt000066400000000000000000000014071455764576500370620ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-none-unicode.out.txt000066400000000000000000000014071455764576500374200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-summary-ascii.out.txt000066400000000000000000000014071455764576500376200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-summary-unicode.out.txt000066400000000000000000000014071455764576500401560ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-testfeed-ascii.out.txt000066400000000000000000000012421455764576500377230ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failJUnit Jupiter > Fail > failWithMultiLineMessage() :: STARTED JUnit Jupiter > Fail > failWithMultiLineMessage() :: FAILED org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-testfeed-unicode.out.txt000066400000000000000000000012421455764576500402610ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failJUnit Jupiter > Fail > failWithMultiLineMessage() :: STARTED JUnit Jupiter > Fail > failWithMultiLineMessage() :: FAILED org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-tree-ascii.out.txt000066400000000000000000000016151455764576500370630ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail. '-- JUnit Jupiter [OK] '-- Fail [OK] '-- failWithMultiLineMessage() [X] multi line fail message Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-tree-unicode.out.txt000066400000000000000000000016501455764576500374200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail╷ └─ JUnit Jupiter ✔ └─ Fail ✔ └─ failWithMultiLineMessage() ✘ multi line fail message Failures (1): JUnit Jupiter:Fail:failWithMultiLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: multi line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-verbose-ascii.out.txt000066400000000000000000000025521455764576500375720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Fail | | +-- failWithMultiLineMessage() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] | | | caught: org.opentest4j.AssertionFailedError: multi | | | line | | | fail | | | message >> S T A C K T R A C E >> \| \| \| duration: [\d]+ ms | | | status: [X] FAILED \| '-- Fail finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithMultiLineMessage-verbose-unicode.out.txt000066400000000000000000000027351455764576500401330ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Fail │ │ ├─ failWithMultiLineMessage() │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithMultiLineMessage()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithMultiLineMessage', methodParameterTypes = ''] │ │ │ caught: org.opentest4j.AssertionFailedError: multi │ │ │ line │ │ │ fail │ │ │ message >> S T A C K T R A C E >> │ │ │ duration: [\d]+ ms │ │ │ status: ✘ FAILED │ └─ Fail finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-flat-ascii.out.txt000066400000000000000000000024541455764576500372030ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Started: failWithSingleLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()]) Finished: failWithSingleLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()]) => Exception: org.opentest4j.AssertionFailedError: single line fail message >> S T A C K T R A C E >> Finished: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-flat-unicode.out.txt000066400000000000000000000024541455764576500375410ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Started: failWithSingleLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()]) Finished: failWithSingleLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()]) => Exception: org.opentest4j.AssertionFailedError: single line fail message >> S T A C K T R A C E >> Finished: Fail ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-none-ascii.out.txt000066400000000000000000000014121455764576500372050ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-none-unicode.out.txt000066400000000000000000000014121455764576500375430ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-summary-ascii.out.txt000066400000000000000000000014121455764576500377430ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-summary-unicode.out.txt000066400000000000000000000014121455764576500403010ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-testfeed-ascii.out.txt000066400000000000000000000012421455764576500400520ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failJUnit Jupiter > Fail > failWithSingleLineMessage() :: STARTED JUnit Jupiter > Fail > failWithSingleLineMessage() :: FAILED org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-testfeed-unicode.out.txt000066400000000000000000000012421455764576500404100ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failJUnit Jupiter > Fail > failWithSingleLineMessage() :: STARTED JUnit Jupiter > Fail > failWithSingleLineMessage() :: FAILED org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-tree-ascii.out.txt000066400000000000000000000015641455764576500372150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail. '-- JUnit Jupiter [OK] '-- Fail [OK] '-- failWithSingleLineMessage() [X] single line fail message Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-tree-unicode.out.txt000066400000000000000000000016001455764576500375420ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/fail╷ └─ JUnit Jupiter ✔ └─ Fail ✔ └─ failWithSingleLineMessage() ✘ single line fail message Failures (1): JUnit Jupiter:Fail:failWithSingleLineMessage() MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] => org.opentest4j.AssertionFailedError: single line fail message >> STACKTRACE >> Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-verbose-ascii.out.txt000066400000000000000000000024651455764576500377240ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Fail | | +-- failWithSingleLineMessage() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] | | | caught: org.opentest4j.AssertionFailedError: single line fail message >> S T A C K T R A C E >> \| \| \| duration: [\d]+ ms | | | status: [X] FAILED \| '-- Fail finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] Fail-failWithSingleLineMessage-verbose-unicode.out.txt000066400000000000000000000026151455764576500402570ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/failTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Fail │ │ ├─ failWithSingleLineMessage() │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase]/[method:failWithSingleLineMessage()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$FailTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$FailTestCase', methodName = 'failWithSingleLineMessage', methodParameterTypes = ''] │ │ │ caught: org.opentest4j.AssertionFailedError: single line fail message >> S T A C K T R A C E >> │ │ │ duration: [\d]+ ms │ │ │ status: ✘ FAILED │ └─ Fail finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 1 tests failed ] junit5-r5.10.2/platform-tests/src/test/resources/console/details/report/000077500000000000000000000000001455764576500263755ustar00rootroot00000000000000Report-reportMultiEntriesWithMultiMappings-flat-ascii.out.txt000066400000000000000000000046001455764576500423760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'dk38', award year = '1974'\] Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, single = 'mapping'\] Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'st77', award year = '1977', last seen = '2001'\] Finished: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-flat-unicode.out.txt000066400000000000000000000046001455764576500427340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'dk38', award year = '1974'\] Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, single = 'mapping'\] Reported: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'st77', award year = '1977', last seen = '2001'\] Finished: reportMultiEntriesWithMultiMappings(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-none-ascii.out.txt000066400000000000000000000000011455764576500423760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultiEntriesWithMultiMappings-none-unicode.out.txt000066400000000000000000000000011455764576500427340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultiEntriesWithMultiMappings-summary-ascii.out.txt000066400000000000000000000007221455764576500431460ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-summary-unicode.out.txt000066400000000000000000000007221455764576500435040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-testfeed-ascii.out.txt000066400000000000000000000012011455764576500432450ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultiEntriesWithMultiMappings(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultiEntriesWithMultiMappings(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-testfeed-unicode.out.txt000066400000000000000000000012011455764576500436030ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultiEntriesWithMultiMappings(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultiEntriesWithMultiMappings(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-tree-ascii.out.txt000066400000000000000000000014631455764576500424130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report. '-- JUnit Jupiter [OK] '-- Report [OK] '-- reportMultiEntriesWithMultiMappings(TestReporter) [OK] ....-..-..T..:...* user name = `dk38` award year = `1974` ....-..-..T..:...* single = `mapping` ....-..-..T..:...* user name = `st77` award year = `1977` last seen = `2001` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-tree-unicode.out.txt000066400000000000000000000015431455764576500427500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report╷ └─ JUnit Jupiter ✔ └─ Report ✔ └─ reportMultiEntriesWithMultiMappings(TestReporter) ✔ ....-..-..T..:...* user name = `dk38` award year = `1974` ....-..-..T..:...* single = `mapping` ....-..-..T..:...* user name = `st77` award year = `1977` last seen = `2001` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-verbose-ascii.out.txt000066400000000000000000000032141455764576500431150ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Report | | +-- reportMultiEntriesWithMultiMappings(TestReporter) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultiEntriesWithMultiMappings', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'dk38', award year = '1974'\] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, single = 'mapping'\] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'st77', award year = '1977', last seen = '2001'\] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Report finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithMultiMappings-verbose-unicode.out.txt000066400000000000000000000033541455764576500434600ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Report │ │ ├─ reportMultiEntriesWithMultiMappings(TestReporter) │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithMultiMappings(org.junit.jupiter.api.TestReporter)] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultiEntriesWithMultiMappings', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'dk38', award year = '1974'\] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, single = 'mapping'\] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, user name = 'st77', award year = '1977', last seen = '2001'\] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Report finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-flat-ascii.out.txt000066400000000000000000000037411455764576500423470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Reported: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] Reported: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, far = 'boo'\] Finished: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-flat-unicode.out.txt000066400000000000000000000037411455764576500427050ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Reported: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] Reported: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, far = 'boo'\] Finished: reportMultiEntriesWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-none-ascii.out.txt000066400000000000000000000000011455764576500423420ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultiEntriesWithSingleMapping-none-unicode.out.txt000066400000000000000000000000011455764576500427000ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultiEntriesWithSingleMapping-summary-ascii.out.txt000066400000000000000000000007221455764576500431120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-summary-unicode.out.txt000066400000000000000000000007221455764576500434500ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-testfeed-ascii.out.txt000066400000000000000000000012011455764576500432110ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultiEntriesWithSingleMapping(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultiEntriesWithSingleMapping(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-testfeed-unicode.out.txt000066400000000000000000000012011455764576500435470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultiEntriesWithSingleMapping(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultiEntriesWithSingleMapping(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-tree-ascii.out.txt000066400000000000000000000012121455764576500423470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report. '-- JUnit Jupiter [OK] '-- Report [OK] '-- reportMultiEntriesWithSingleMapping(TestReporter) [OK] ....-..-..T..:...* foo = `bar` ....-..-..T..:...* far = `boo` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-tree-unicode.out.txt000066400000000000000000000012351455764576500427120ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report╷ └─ JUnit Jupiter ✔ └─ Report ✔ └─ reportMultiEntriesWithSingleMapping(TestReporter) ✔ ....-..-..T..:...* foo = `bar` ....-..-..T..:...* far = `boo` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-verbose-ascii.out.txt000066400000000000000000000027511455764576500430660ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Report | | +-- reportMultiEntriesWithSingleMapping(TestReporter) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultiEntriesWithSingleMapping', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, far = 'boo'\] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Report finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultiEntriesWithSingleMapping-verbose-unicode.out.txt000066400000000000000000000031031455764576500434140ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Report │ │ ├─ reportMultiEntriesWithSingleMapping(TestReporter) │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultiEntriesWithSingleMapping(org.junit.jupiter.api.TestReporter)] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultiEntriesWithSingleMapping', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, far = 'boo'\] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Report finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-flat-ascii.out.txt000066400000000000000000000035751455764576500377010ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) Reported: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] Reported: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'bar'\] Finished: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-flat-unicode.out.txt000066400000000000000000000035751455764576500402370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) Reported: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] Reported: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'bar'\] Finished: reportMultipleMessages(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-none-ascii.out.txt000066400000000000000000000000011455764576500376670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultipleMessages-none-unicode.out.txt000066400000000000000000000000011455764576500402250ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportMultipleMessages-summary-ascii.out.txt000066400000000000000000000007221455764576500404370ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-summary-unicode.out.txt000066400000000000000000000007221455764576500407750ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-testfeed-ascii.out.txt000066400000000000000000000011471455764576500405470ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultipleMessages(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultipleMessages(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-testfeed-unicode.out.txt000066400000000000000000000011471455764576500411050ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportMultipleMessages(TestReporter) :: STARTED JUnit Jupiter > Report > reportMultipleMessages(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-tree-ascii.out.txt000066400000000000000000000012011455764576500376720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report. '-- JUnit Jupiter [OK] '-- Report [OK] '-- reportMultipleMessages(TestReporter) [OK] ....-..-..T..:...* value = `foo` ....-..-..T..:...* value = `bar` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-tree-unicode.out.txt000066400000000000000000000012241455764576500402350ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report╷ └─ JUnit Jupiter ✔ └─ Report ✔ └─ reportMultipleMessages(TestReporter) ✔ ....-..-..T..:...* value = `foo` ....-..-..T..:...* value = `bar` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-verbose-ascii.out.txt000066400000000000000000000027061455764576500404130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Report | | +-- reportMultipleMessages(TestReporter) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultipleMessages', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'bar'\] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Report finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportMultipleMessages-verbose-unicode.out.txt000066400000000000000000000030401455764576500407410ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Report │ │ ├─ reportMultipleMessages(TestReporter) │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportMultipleMessages(org.junit.jupiter.api.TestReporter)] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportMultipleMessages', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'bar'\] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Report finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-flat-ascii.out.txt000066400000000000000000000032171455764576500421640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Reported: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] Finished: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-flat-unicode.out.txt000066400000000000000000000032171455764576500425220ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Reported: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] Finished: reportSingleEntryWithSingleMapping(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-none-ascii.out.txt000066400000000000000000000000011455764576500421610ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportSingleEntryWithSingleMapping-none-unicode.out.txt000066400000000000000000000000011455764576500425170ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportSingleEntryWithSingleMapping-summary-ascii.out.txt000066400000000000000000000007221455764576500427310ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-summary-unicode.out.txt000066400000000000000000000007221455764576500432670ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-testfeed-ascii.out.txt000066400000000000000000000011771455764576500430440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportSingleEntryWithSingleMapping(TestReporter) :: STARTED JUnit Jupiter > Report > reportSingleEntryWithSingleMapping(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-testfeed-unicode.out.txt000066400000000000000000000011771455764576500434020ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportSingleEntryWithSingleMapping(TestReporter) :: STARTED JUnit Jupiter > Report > reportSingleEntryWithSingleMapping(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-tree-ascii.out.txt000066400000000000000000000011421455764576500421700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report. '-- JUnit Jupiter [OK] '-- Report [OK] '-- reportSingleEntryWithSingleMapping(TestReporter) [OK] ....-..-..T..:...* foo = `bar` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-tree-unicode.out.txt000066400000000000000000000011611455764576500425270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report╷ └─ JUnit Jupiter ✔ └─ Report ✔ └─ reportSingleEntryWithSingleMapping(TestReporter) ✔ ....-..-..T..:...* foo = `bar` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-verbose-ascii.out.txt000066400000000000000000000026261455764576500427060ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Report | | +-- reportSingleEntryWithSingleMapping(TestReporter) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportSingleEntryWithSingleMapping', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Report finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleEntryWithSingleMapping-verbose-unicode.out.txt000066400000000000000000000027521455764576500432440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Report │ │ ├─ reportSingleEntryWithSingleMapping(TestReporter) │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleEntryWithSingleMapping(org.junit.jupiter.api.TestReporter)] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportSingleEntryWithSingleMapping', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, foo = 'bar'\] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Report finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-flat-ascii.out.txt000066400000000000000000000030671455764576500371400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) Reported: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] Finished: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-flat-unicode.out.txt000066400000000000000000000030671455764576500374760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Started: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) Reported: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) => Reported values: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] Finished: reportSingleMessage(TestReporter) ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)]) Finished: Report ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-none-ascii.out.txt000066400000000000000000000000011455764576500371320ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportSingleMessage-none-unicode.out.txt000066400000000000000000000000011455764576500374700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Report-reportSingleMessage-summary-ascii.out.txt000066400000000000000000000007221455764576500377020ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-summary-unicode.out.txt000066400000000000000000000007221455764576500402400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-testfeed-ascii.out.txt000066400000000000000000000011411455764576500400040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportSingleMessage(TestReporter) :: STARTED JUnit Jupiter > Report > reportSingleMessage(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-testfeed-unicode.out.txt000066400000000000000000000011411455764576500403420ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportJUnit Jupiter > Report > reportSingleMessage(TestReporter) :: STARTED JUnit Jupiter > Report > reportSingleMessage(TestReporter) :: SUCCESSFUL Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-tree-ascii.out.txt000066400000000000000000000011251455764576500371420ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report. '-- JUnit Jupiter [OK] '-- Report [OK] '-- reportSingleMessage(TestReporter) [OK] ....-..-..T..:...* value = `foo` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-tree-unicode.out.txt000066400000000000000000000011441455764576500375010ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/report╷ └─ JUnit Jupiter ✔ └─ Report ✔ └─ reportSingleMessage(TestReporter) ✔ ....-..-..T..:...* value = `foo` Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-verbose-ascii.out.txt000066400000000000000000000025531455764576500376560ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Report | | +-- reportSingleMessage(TestReporter) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportSingleMessage', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] \| \| \| reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] \| \| \| duration: [\d]+ ms | | | status: [OK] SUCCESSFUL \| '-- Report finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] Report-reportSingleMessage-verbose-unicode.out.txt000066400000000000000000000026771455764576500402230ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/reportTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Report │ │ ├─ reportSingleMessage(TestReporter) │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase]/[method:reportSingleMessage(org.junit.jupiter.api.TestReporter)] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$ReportTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$ReportTestCase', methodName = 'reportSingleMessage', methodParameterTypes = 'org.junit.jupiter.api.TestReporter'] │ │ │ reports: ReportEntry \[timestamp = ....-..-..T..:...*, value = 'foo'\] │ │ │ duration: [\d]+ ms │ │ │ status: ✔ SUCCESSFUL │ └─ Report finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 0 tests aborted ] [ 1 tests successful ] [ 0 tests failed ] junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip/000077500000000000000000000000001455764576500260305ustar00rootroot00000000000000Skip-skipWithMultiLineMessage-flat-ascii.out.txt000066400000000000000000000021431455764576500371700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Skipped: skipWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithMultiLineMessage()]) => Reason: multi line fail message Finished: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-flat-unicode.out.txt000066400000000000000000000021431455764576500375260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Skipped: skipWithMultiLineMessage() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithMultiLineMessage()]) => Reason: multi line fail message Finished: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-none-ascii.out.txt000066400000000000000000000000011455764576500371700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Skip-skipWithMultiLineMessage-none-unicode.out.txt000066400000000000000000000000011455764576500375260ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Skip-skipWithMultiLineMessage-summary-ascii.out.txt000066400000000000000000000007221455764576500377400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-summary-unicode.out.txt000066400000000000000000000007221455764576500402760ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-testfeed-ascii.out.txt000066400000000000000000000010631455764576500400450ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipJUnit Jupiter > Skip > skipWithMultiLineMessage() :: SKIPPED Reason: multi line fail message Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-testfeed-unicode.out.txt000066400000000000000000000010631455764576500404030ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipJUnit Jupiter > Skip > skipWithMultiLineMessage() :: SKIPPED Reason: multi line fail message Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-tree-ascii.out.txt000066400000000000000000000011301455764576500371740ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip. '-- JUnit Jupiter [OK] '-- Skip [OK] '-- skipWithMultiLineMessage() [S] multi line fail message Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-tree-unicode.out.txt000066400000000000000000000011631455764576500375400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip╷ └─ JUnit Jupiter ✔ └─ Skip ✔ └─ skipWithMultiLineMessage() ↷ multi line fail message Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-verbose-ascii.out.txt000066400000000000000000000024171455764576500377130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Skip | | +-- skipWithMultiLineMessage() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithMultiLineMessage()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$SkipTestCase', methodName = 'skipWithMultiLineMessage', methodParameterTypes = ''] | | | reason: multi | | | line | | | fail | | | message | | | status: [S] SKIPPED \| '-- Skip finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithMultiLineMessage-verbose-unicode.out.txt000066400000000000000000000025741455764576500402550ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Skip │ │ ├─ skipWithMultiLineMessage() │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithMultiLineMessage()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$SkipTestCase', methodName = 'skipWithMultiLineMessage', methodParameterTypes = ''] │ │ │ reason: multi │ │ │ line │ │ │ fail │ │ │ message │ │ │ status: ↷ SKIPPED │ └─ Skip finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-flat-ascii.out.txt000066400000000000000000000020741455764576500371650ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Skipped: skipWithSingleLineReason() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithSingleLineReason()]) => Reason: single line skip reason Finished: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-flat-unicode.out.txt000066400000000000000000000020741455764576500375230ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest execution started. Number of static tests: 1 Started: JUnit Jupiter ([engine:junit-jupiter]) Started: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Skipped: skipWithSingleLineReason() ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithSingleLineReason()]) => Reason: single line skip reason Finished: Skip ([engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]) Finished: JUnit Jupiter ([engine:junit-jupiter]) Test execution finished. Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-none-ascii.out.txt000066400000000000000000000000011455764576500371620ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Skip-skipWithSingleLineReason-none-unicode.out.txt000066400000000000000000000000011455764576500375200ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Skip-skipWithSingleLineReason-summary-ascii.out.txt000066400000000000000000000007221455764576500377320ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-summary-unicode.out.txt000066400000000000000000000007221455764576500402700ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-testfeed-ascii.out.txt000066400000000000000000000010601455764576500400340ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipJUnit Jupiter > Skip > skipWithSingleLineReason() :: SKIPPED Reason: single line skip reason Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-testfeed-unicode.out.txt000066400000000000000000000010601455764576500403720ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipJUnit Jupiter > Skip > skipWithSingleLineReason() :: SKIPPED Reason: single line skip reason Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-tree-ascii.out.txt000066400000000000000000000010721455764576500371730ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip. '-- JUnit Jupiter [OK] '-- Skip [OK] '-- skipWithSingleLineReason() [S] single line skip reason Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-tree-unicode.out.txt000066400000000000000000000011061455764576500375270ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skip╷ └─ JUnit Jupiter ✔ └─ Skip ✔ └─ skipWithSingleLineReason() ↷ single line skip reason Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-verbose-ascii.out.txt000066400000000000000000000023261455764576500377040ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest plan execution started. Number of static tests: 1 . +-- JUnit Jupiter | +-- Skip | | +-- skipWithSingleLineReason() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithSingleLineReason()] | | | parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase] | | | source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$SkipTestCase', methodName = 'skipWithSingleLineReason', methodParameterTypes = ''] | | | reason: single line skip reason | | | status: [S] SKIPPED \| '-- Skip finished after [\d]+ ms\. '-- JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] Skip-skipWithSingleLineReason-verbose-unicode.out.txt000066400000000000000000000024501455764576500402400ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/console/details/skipTest plan execution started. Number of static tests: 1 ╷ ├─ JUnit Jupiter │ ├─ Skip │ │ ├─ skipWithSingleLineReason() │ │ │ tags: [] │ │ │ uniqueId: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase]/[method:skipWithSingleLineReason()] │ │ │ parent: [engine:junit-jupiter]/[class:org.junit.platform.console.ConsoleDetailsTests$SkipTestCase] │ │ │ source: MethodSource [className = 'org.junit.platform.console.ConsoleDetailsTests$SkipTestCase', methodName = 'skipWithSingleLineReason', methodParameterTypes = ''] │ │ │ reason: single line skip reason │ │ │ status: ↷ SKIPPED │ └─ Skip finished after [\d]+ ms\. └─ JUnit Jupiter finished after [\d]+ ms\. Test plan execution finished. Number of all tests: 1 Test run finished after [\d]+ ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 1 tests skipped ] [ 0 tests started ] [ 0 tests aborted ] [ 0 tests successful ] [ 0 tests failed ] junit5-r5.10.2/platform-tests/src/test/resources/do_not_delete_me.txt000066400000000000000000000000541455764576500260200ustar00rootroot00000000000000I am used by tests, so... Do NOT delete me!junit5-r5.10.2/platform-tests/src/test/resources/folder with spaces/000077500000000000000000000000001455764576500254415ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/folder with spaces/jar test with spaces.jar000066400000000000000000000047661455764576500320630ustar00rootroot00000000000000PKZH META-INF/PKPKZHMETA-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu X[*h%&*8%krrPK CDPK TYHorg/PK TYH org/junit/PK TYHorg/junit/platform/PK TYHorg/junit/platform/jartest/PK TYH$org/junit/platform/jartest/included/PKTYH2org/junit/platform/jartest/included/Included.classOMK@}ӤHMR7Z7l< QX@g1͛{$AaQ1!zеzMTqklsV27L3[HN$]̺F7붢Ϋ.LSR<{B+ԓnCy%?e}9I{*75T1Cl91b&:oA_<3F13Iw>\PKudAPK TYH.org/junit/platform/jartest/included/recursive/PKTYHGorg/junit/platform/jartest/included/recursive/RecursivelyIncluded.classPJ@}s%wXک)AAf=7%= ?'܁Ǽo|~84C{)&4_!&L 蛰*{eeh L7bLG[:px?n%j0ҕpZיw}68O>sZ˵cLF´V6Kq[Zybķq"Ƅ80>yr3Bʘ b-ǀmdʿPKUvPK TYH'org/junit/platform/jartest/notincluded/PKTYH8org/junit/platform/jartest/notincluded/NotIncluded.classJ@ihozpAzSCKd^>%zu~w0$C)Ƅ^[tM]B[5o+YN. WI^wUhZ7#Ë[H.낶ikU χ-]+;撚2G!hua݈E٨*{dք=0}p3@ʚao#di?PK KPPKZH META-INF/PKZH CD=META-INF/MANIFEST.MFPK TYHorg/PK TYH org/junit/PK TYH org/junit/platform/PK TYH=org/junit/platform/jartest/PK TYH$vorg/junit/platform/jartest/included/PKTYHudA2org/junit/platform/jartest/included/Included.classPK TYH.org/junit/platform/jartest/included/recursive/PKTYHUvGBorg/junit/platform/jartest/included/recursive/RecursivelyIncluded.classPK TYH'org/junit/platform/jartest/notincluded/PKTYH KP8org/junit/platform/jartest/notincluded/NotIncluded.classPK 1junit5-r5.10.2/platform-tests/src/test/resources/gh-1436-invalid-nested-class-file.jar000066400000000000000000000046001455764576500304060ustar00rootroot00000000000000PK L META-INF/PK LMETA-INF/MANIFEST.MFMLK-. K-*ϳR03PK Ltests/PK Ls`>&tests/NestedInterfaceGroovyTests.classWk[G~'YXBP/(IDX5jP B#m,a!즻 ^W~鶴by|ڞ] Bd\s;g& ,ŴXJKcDN+OM-zLc9YzϏ)iKacs2m8d7dZsivi#:C4XZ(s]H 3dcP,fO #ZCM(Xr.T-0d/1YKI9ŸjCPZ @zZnl@3b {CLj:>m)\-#"(RF1"g*GE?XD`ZꜲFL>if0d csH(u1{ gp#9D Wld#k.ޛTZ_2[னX+#.z(â#Qgh;:xg(s"Yng>[ ǫgO4`i\H' = C j}}HrJ`^"^4չJ%E9 Ky^M:ag]!knL:M1dT 8O&M0U%i+f~=Sv5[F a E+rir9nrL&_ttֆҋTXR^ZJZʒ@#J]^O';a"^_Ұ2`oJ0a36e"=lqس.rILq.}@4:Կd'_{V.O*)OIQВ-S\Hi_^_ڭNPz9a J m󧛮W\z[λRFܮBہ>ijNvJ@(P |?hzH4~K&V,j[oDAWK<؜af0"^ʂ>QK:G٦Gk(+65;Ų#6l'fMͷ1&`Cel$n^rTnC{jvqxs>@MLD_+Nh:.G 7=R8Y|HʗRz.R"?[TVÏn澠ϗ _Mu~i"PK LQ`\6tests/NestedInterfaceGroovyTests$NestedInterface.class;o>cnFb}? WZ^_VRAbg`ddJ,KIKOJM.ag`fdPm^:Ƞ@>v6F~4yFϼ"bFҢT̜Tr&`b\ 1vXPK L AMETA-INF/PK L)META-INF/MANIFEST.MFPK LAvtests/PK Ls`>&tests/NestedInterfaceGroovyTests.classPK LQ`\6tests/NestedInterfaceGroovyTests$NestedInterface.classPKejunit5-r5.10.2/platform-tests/src/test/resources/intercepted-testservices/000077500000000000000000000000001455764576500270225ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/intercepted-testservices/META-INF/000077500000000000000000000000001455764576500301625ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/000077500000000000000000000000001455764576500320055ustar00rootroot00000000000000org.junit.platform.engine.TestEngine000066400000000000000000000000621455764576500407210ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/intercepted-testservices/META-INF/servicesorg.junit.platform.launcher.InterceptedTestEngine org.junit.platform.launcher.LauncherSessionListener000066400000000000000000000001071455764576500440230ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/intercepted-testservices/META-INF/servicesorg.junit.platform.launcher.InterceptorInjectedLauncherSessionListener junit5-r5.10.2/platform-tests/src/test/resources/jartest.jar000066400000000000000000000047661455764576500241620ustar00rootroot00000000000000PKZH META-INF/PKPKZHMETA-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu X[*h%&*8%krrPK CDPK TYHorg/PK TYH org/junit/PK TYHorg/junit/platform/PK TYHorg/junit/platform/jartest/PK TYH$org/junit/platform/jartest/included/PKTYH2org/junit/platform/jartest/included/Included.classOMK@}ӤHMR7Z7l< QX@g1͛{$AaQ1!zеzMTqklsV27L3[HN$]̺F7붢Ϋ.LSR<{B+ԓnCy%?e}9I{*75T1Cl91b&:oA_<3F13Iw>\PKudAPK TYH.org/junit/platform/jartest/included/recursive/PKTYHGorg/junit/platform/jartest/included/recursive/RecursivelyIncluded.classPJ@}s%wXک)AAf=7%= ?'܁Ǽo|~84C{)&4_!&L 蛰*{eeh L7bLG[:px?n%j0ҕpZיw}68O>sZ˵cLF´V6Kq[Zybķq"Ƅ80>yr3Bʘ b-ǀmdʿPKUvPK TYH'org/junit/platform/jartest/notincluded/PKTYH8org/junit/platform/jartest/notincluded/NotIncluded.classJ@ihozpAzSCKd^>%zu~w0$C)Ƅ^[tM]B[5o+YN. WI^wUhZ7#Ë[H.낶ikU χ-]+;撚2G!hua݈E٨*{dք=0}p3@ʚao#di?PK KPPKZH META-INF/PKZH CD=META-INF/MANIFEST.MFPK TYHorg/PK TYH org/junit/PK TYH org/junit/platform/PK TYH=org/junit/platform/jartest/PK TYH$vorg/junit/platform/jartest/included/PKTYHudA2org/junit/platform/jartest/included/Included.classPK TYH.org/junit/platform/jartest/included/recursive/PKTYHUvGBorg/junit/platform/jartest/included/recursive/RecursivelyIncluded.classPK TYH'org/junit/platform/jartest/notincluded/PKTYH KP8org/junit/platform/jartest/notincluded/NotIncluded.classPK 1junit5-r5.10.2/platform-tests/src/test/resources/jenkins-junit.xsd000066400000000000000000000137341455764576500253130ustar00rootroot00000000000000 junit5-r5.10.2/platform-tests/src/test/resources/listeners/000077500000000000000000000000001455764576500240035ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/000077500000000000000000000000001455764576500263075ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/000077500000000000000000000000001455764576500275455ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/groovy/000077500000000000000000000000001455764576500310725ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/groovy/build.gradle000066400000000000000000000000771455764576500333550ustar00rootroot00000000000000// This file is used in tests for the UniqueIdTrackingListener junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/groovy/sub-project/000077500000000000000000000000001455764576500333275ustar00rootroot00000000000000sub-project.gradle000066400000000000000000000000771455764576500366710ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/groovy/sub-project// This file is used in tests for the UniqueIdTrackingListener junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/kotlin/000077500000000000000000000000001455764576500310455ustar00rootroot00000000000000build.gradle.kts000066400000000000000000000000771455764576500340510ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/kotlin// This file is used in tests for the UniqueIdTrackingListener junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/kotlin/sub-project/000077500000000000000000000000001455764576500333025ustar00rootroot00000000000000sub-project.gradle.kts000066400000000000000000000000771455764576500374440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/gradle/kotlin/sub-project// This file is used in tests for the UniqueIdTrackingListener junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/maven/000077500000000000000000000000001455764576500274155ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/listeners/uidtracking/maven/pom.xml000066400000000000000000000001051455764576500307260ustar00rootroot00000000000000 junit5-r5.10.2/platform-tests/src/test/resources/log4j2-test.xml000066400000000000000000000021571455764576500246000ustar00rootroot00000000000000 junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/000077500000000000000000000000001455764576500240275ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo.bar/000077500000000000000000000000001455764576500253555ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo.bar/FooBar.java000066400000000000000000000000511455764576500273640ustar00rootroot00000000000000package foo.bar; public class FooBar {} junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo.bar/module-info.java000066400000000000000000000000501455764576500304310ustar00rootroot00000000000000open module foo.bar { requires foo; } junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo/000077500000000000000000000000001455764576500246125ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo/Foo.java000066400000000000000000000000421455764576500261740ustar00rootroot00000000000000package foo; public class Foo {} junit5-r5.10.2/platform-tests/src/test/resources/modules-2500/foo/module-info.java000066400000000000000000000000361455764576500276720ustar00rootroot00000000000000module foo { exports foo; } junit5-r5.10.2/platform-tests/src/test/resources/serialized-test-identifier000066400000000000000000000020671455764576500271530ustar00rootroot00000000000000sr*org.junit.platform.launcher.TestIdentifierL displayNametLjava/lang/String;LlegacyReportingNameq~LparentIdq~Lsourcet&Lorg/junit/platform/engine/TestSource;LtagstLjava/util/Set;Ltypet/Lorg/junit/platform/engine/TestDescriptor$Type;LuniqueIdq~xpt displayNamet reportingNamet[engine:engine]sr8org.junit.platform.engine.support.descriptor.ClassSourceL classNameq~L filePositiont;Lorg/junit/platform/engine/support/descriptor/FilePosition;L javaClasstLjava/lang/Class;xpt/org.junit.platform.launcher.TestIdentifierTestspvr/org.junit.platform.launcher.TestIdentifierTestsxpsr%java.util.Collections$UnmodifiableSetяUxr,java.util.Collections$UnmodifiableCollectionB^LctLjava/util/Collection;xpsrjava.util.LinkedHashSetlZ*xrjava.util.HashSetD4xpw ?@sr!org.junit.platform.engine.TestTagLnameq~xptaTagx~r-org.junit.platform.engine.TestDescriptor$Typexrjava.lang.EnumxptTESTt[engine:engine]/[child:child]junit5-r5.10.2/platform-tests/src/test/resources/test-junit-platform.properties000066400000000000000000000001311455764576500300340ustar00rootroot00000000000000org.junit.platform.launcher.core.LauncherConfigurationParametersTests = from config file junit5-r5.10.2/platform-tests/src/test/resources/testservices/000077500000000000000000000000001455764576500245165ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/000077500000000000000000000000001455764576500256565ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/services/000077500000000000000000000000001455764576500275015ustar00rootroot00000000000000org.junit.platform.launcher.LauncherDiscoveryListener000066400000000000000000000000721455764576500420440ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/servicesorg.junit.platform.launcher.TestLauncherDiscoveryListener org.junit.platform.launcher.LauncherInterceptor000066400000000000000000000001521455764576500406640ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/servicesorg.junit.platform.launcher.TestLauncherInterceptor1 org.junit.platform.launcher.TestLauncherInterceptor2 org.junit.platform.launcher.LauncherSessionListener000066400000000000000000000000701455764576500415160ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/servicesorg.junit.platform.launcher.TestLauncherSessionListener org.junit.platform.launcher.PostDiscoveryFilter000066400000000000000000000000671455764576500406740ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/servicesorg.junit.platform.launcher.TestPostDiscoveryTagFilter org.junit.platform.launcher.TestExecutionListener000066400000000000000000000003121455764576500412130ustar00rootroot00000000000000junit5-r5.10.2/platform-tests/src/test/resources/testservices/META-INF/servicesorg.junit.platform.launcher.listeners.NoopTestExecutionListener org.junit.platform.launcher.listeners.UnusedTestExecutionListener org.junit.platform.launcher.listeners.AnotherUnusedTestExecutionListenerjunit5-r5.10.2/platform-tooling-support-tests/000077500000000000000000000000001455764576500213765ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts000066400000000000000000000156211455764576500315320ustar00rootroot00000000000000import com.gradle.enterprise.gradleplugin.testdistribution.internal.TestDistributionExtensionInternal import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.configurationcache.extensions.capitalized import org.gradle.jvm.toolchain.internal.NoToolchainAvailableException import java.time.Duration plugins { id("junitbuild.build-parameters") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") } javaLibrary { mainJavaVersion = JavaVersion.VERSION_11 } spotless { java { target(files(project.java.sourceSets.map { it.allJava }), "projects/**/*.java") } kotlin { target("projects/**/*.kt") } format("projects") { target("projects/**/*.gradle.kts", "projects/**/*.md") trimTrailingWhitespace() endWithNewline() } } val thirdPartyJars by configurations.creatingResolvable val antJars by configurations.creatingResolvable val mavenDistribution by configurations.creatingResolvable dependencies { implementation(libs.bartholdy) { because("manage external tool installations") } implementation(libs.commons.io) { because("moving/deleting directory trees") } testImplementation(libs.archunit) { because("checking the architecture of JUnit 5") } testImplementation(libs.apiguardian) { because("we validate that public classes are annotated") } testImplementation(libs.groovy4) { because("it provides convenience methods to handle process output") } testImplementation(libs.bndlib) { because("parsing OSGi metadata") } testRuntimeOnly(libs.slf4j.julBinding) { because("provide appropriate SLF4J binding") } testImplementation(libs.ant) { because("we reference Ant's main class") } testImplementation(libs.bundles.xmlunit) thirdPartyJars(libs.junit4) thirdPartyJars(libs.assertj) thirdPartyJars(libs.apiguardian) thirdPartyJars(libs.hamcrest) thirdPartyJars(libs.opentest4j) thirdPartyJars(libs.jimfs) antJars(platform(projects.junitBom)) antJars(libs.bundles.ant) antJars(projects.junitPlatformConsoleStandalone) antJars(projects.junitPlatformLauncher) antJars(projects.junitPlatformReporting) mavenDistribution(libs.maven) { artifact { classifier = "bin" type = "zip" isTransitive = false } } } val unzipMavenDistribution by tasks.registering(Sync::class) { from(zipTree(mavenDistribution.elements.map { it.single() })) into(layout.buildDirectory.dir("maven-distribution")) } val normalizeMavenRepo by tasks.registering(Sync::class) { val mavenizedProjects: List by rootProject val tempRepoDir: File by rootProject val tempRepoName: String by rootProject // All maven-aware projects must be published to the local temp repository (mavenizedProjects + projects.junitBom.dependencyProject) .map { project -> project.tasks.named("publishAllPublicationsTo${tempRepoName.capitalized()}Repository") } .forEach { dependsOn(it) } from(tempRepoDir) { exclude("**/maven-metadata.xml*") exclude("**/*.md5") exclude("**/*.sha*") exclude("**/*.module") } from(tempRepoDir) { include("**/*.module") val regex = "\"(sha\\d+|md5|size)\": (?:\".+\"|\\d+)(,)?".toRegex() filter { line -> regex.replace(line, "\"normalized-$1\": \"normalized-value\"$2") } } rename("(.*\\W)\\d{8}\\.\\d{6}-\\d+(\\W.*)", "$1SNAPSHOT$2") into(layout.buildDirectory.dir("normalized-repo")) } tasks.test { // Opt-out via system property: '-Dplatform.tooling.support.tests.enabled=false' enabled = System.getProperty("platform.tooling.support.tests.enabled")?.toBoolean() ?: true // The following if-block is necessary since Gradle will otherwise // always publish all mavenizedProjects even if this "test" task // is not executed. if (enabled) { dependsOn(normalizeMavenRepo) jvmArgumentProviders += MavenRepo(project, normalizeMavenRepo.map { it.destinationDir }) } jvmArgumentProviders += JarPath(project, thirdPartyJars) jvmArgumentProviders += JarPath(project, antJars) jvmArgumentProviders += MavenDistribution(project, unzipMavenDistribution) (options as JUnitPlatformOptions).apply { includeEngines("archunit") } inputs.apply { dir("projects").withPathSensitivity(RELATIVE) file("${rootDir}/gradle.properties").withPathSensitivity(RELATIVE) file("${rootDir}/settings.gradle.kts").withPathSensitivity(RELATIVE) file("${rootDir}/gradlew").withPathSensitivity(RELATIVE) file("${rootDir}/gradlew.bat").withPathSensitivity(RELATIVE) dir("${rootDir}/gradle/wrapper").withPathSensitivity(RELATIVE) dir("${rootDir}/documentation/src/main").withPathSensitivity(RELATIVE) dir("${rootDir}/documentation/src/test").withPathSensitivity(RELATIVE) } distribution { requirements.add("jdk=8") this as TestDistributionExtensionInternal preferredMaxDuration = Duration.ofMillis(500) } jvmArgumentProviders += JavaHomeDir(project, 8, distribution.enabled) } class MavenRepo(project: Project, @get:Internal val repoDir: Provider) : CommandLineArgumentProvider { // Track jars and non-jars separately to benefit from runtime classpath normalization // which ignores timestamp manifest attributes. @InputFiles @Classpath val jarFiles: ConfigurableFileTree = project.fileTree(repoDir) { include("**/*.jar") } @InputFiles @PathSensitive(RELATIVE) val nonJarFiles: ConfigurableFileTree = project.fileTree(repoDir) { exclude("**/*.jar") } override fun asArguments() = listOf("-Dmaven.repo=${repoDir.get().absolutePath}") } class JavaHomeDir(project: Project, @Input val version: Int, testDistributionEnabled: Provider) : CommandLineArgumentProvider { @Internal val javaLauncher: Property = project.objects.property() .value(project.provider { try { project.javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(version) }.get() } catch (e: NoToolchainAvailableException) { null } }) @Internal val enabled: Property = project.objects.property().convention(testDistributionEnabled.map { !it }) override fun asArguments(): List { if (!enabled.get()) { return emptyList() } val metadata = javaLauncher.map { it.metadata } val javaHome = metadata.map { it.installationPath.asFile.absolutePath }.orNull return javaHome?.let { listOf("-Djava.home.$version=$it") } ?: emptyList() } } class JarPath(project: Project, configuration: Configuration, @Input val key: String = configuration.name) : CommandLineArgumentProvider { @get:Classpath val files: ConfigurableFileCollection = project.objects.fileCollection().from(configuration) override fun asArguments() = listOf("-D${key}=${files.asPath}") } class MavenDistribution(project: Project, sourceTask: TaskProvider<*>) : CommandLineArgumentProvider { @InputDirectory @PathSensitive(RELATIVE) val mavenDistribution: DirectoryProperty = project.objects.directoryProperty() .value(project.layout.dir(sourceTask.map { it.outputs.files.singleFile.listFiles()!!.single() })) override fun asArguments() = listOf("-DmavenDistribution=${mavenDistribution.get().asFile.absolutePath}") } junit5-r5.10.2/platform-tooling-support-tests/projects/000077500000000000000000000000001455764576500232275ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/000077500000000000000000000000001455764576500254735ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/build.xml000066400000000000000000000053131455764576500273160ustar00rootroot00000000000000 junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/000077500000000000000000000000001455764576500262625ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/000077500000000000000000000000001455764576500272065ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/java/000077500000000000000000000000001455764576500301275ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/java/com/000077500000000000000000000000001455764576500307055ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/java/com/example/000077500000000000000000000000001455764576500323405ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500337275ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/java/com/exampleCalculator.java000066400000000000000000000006521455764576500366660ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/main/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; public class Calculator { public int add(int a, int b) { return a + b; } } junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/000077500000000000000000000000001455764576500272415ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/java/000077500000000000000000000000001455764576500301625ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/java/com/000077500000000000000000000000001455764576500307405ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/java/com/example/000077500000000000000000000000001455764576500323735ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500337625ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/java/com/exampleCalculatorTests.java000066400000000000000000000022271455764576500377440ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/ant-starter/src/test/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class CalculatorTests { @Test @DisplayName("1 + 1 = 2") void addsTwoNumbers() { Calculator calculator = new Calculator(); assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2"); } @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({ // "0, 1, 1", // "1, 2, 3", // "49, 51, 100", // "1, 100, 101" // }) void add(int first, int second, int expectedResult) { Calculator calculator = new Calculator(); assertEquals(expectedResult, calculator.add(first, second), () -> first + " + " + second + " should equal " + expectedResult); } } junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/000077500000000000000000000000001455764576500263425ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts000066400000000000000000000020701455764576500314200ustar00rootroot00000000000000plugins { java id("org.graalvm.buildtools.native") } val jupiterVersion: String = System.getenv("JUNIT_JUPITER_VERSION") val platformVersion: String = System.getenv("JUNIT_PLATFORM_VERSION") repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() } dependencies { testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") testRuntimeOnly("org.junit.platform:junit-platform-reporting:$platformVersion") } tasks.test { useJUnitPlatform() val outputDir = reports.junitXml.outputLocation jvmArgumentProviders += CommandLineArgumentProvider { listOf( "-Djunit.platform.reporting.open.xml.enabled=true", "-Djunit.platform.reporting.output.dir=${outputDir.get().asFile.absolutePath}" ) } } graalvmNative { binaries { named("test") { buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig") buildArgs.add("--initialize-at-build-time=org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter") buildArgs.add("-H:+ReportExceptionStackTraces") } } } junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/gradle.properties000066400000000000000000000000631455764576500317150ustar00rootroot00000000000000org.gradle.java.installations.fromEnv=GRAALVM_HOME junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts000066400000000000000000000003311455764576500321570ustar00rootroot00000000000000pluginManagement { plugins { id("org.graalvm.buildtools.native") version "0.9.13" } repositories { mavenCentral() gradlePluginPortal() } } rootProject.name = "graalvm-starter" junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/000077500000000000000000000000001455764576500271315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/000077500000000000000000000000001455764576500300555ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/java/000077500000000000000000000000001455764576500307765ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/java/com/000077500000000000000000000000001455764576500315545ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/java/com/example/000077500000000000000000000000001455764576500332075ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500345765ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/java/com/exampleCalculator.java000066400000000000000000000006521455764576500375350ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/main/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; public class Calculator { public int add(int a, int b) { return a + b; } } junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/000077500000000000000000000000001455764576500301105ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/java/000077500000000000000000000000001455764576500310315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/java/com/000077500000000000000000000000001455764576500316075ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/java/com/example/000077500000000000000000000000001455764576500332425ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500346315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/java/com/exampleCalculatorTests.java000066400000000000000000000022271455764576500406130ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/graalvm-starter/src/test/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class CalculatorTests { @Test @DisplayName("1 + 1 = 2") void addsTwoNumbers() { Calculator calculator = new Calculator(); assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2"); } @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({ // "0, 1, 1", // "1, 2, 3", // "49, 51, 100", // "1, 100, 101" // }) void add(int first, int second, int expectedResult) { Calculator calculator = new Calculator(); assertEquals(expectedResult, calculator.add(first, second), () -> first + " + " + second + " should equal " + expectedResult); } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/000077500000000000000000000000001455764576500301605ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts000066400000000000000000000012341455764576500332370ustar00rootroot00000000000000import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("jvm") version "1.2.71" } repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() } // grab jupiter version from system environment val jupiterVersion = System.getenv("JUNIT_JUPITER_VERSION") dependencies { testImplementation(kotlin("stdlib-jdk8")) testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") } tasks.withType().configureEach { kotlinOptions { jvmTarget = "1.8" apiVersion = "1.1" languageVersion = "1.1" } } tasks.test { useJUnitPlatform() testLogging { events("passed", "skipped", "failed") } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle/000077500000000000000000000000001455764576500314165ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle/wrapper/000077500000000000000000000000001455764576500330765ustar00rootroot00000000000000gradle-wrapper.jar000066400000000000000000001545001455764576500364360ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle/wrapperPK A META-INF/PK Am>=@?META-INF/MANIFEST.MFMLK-. K-*ϳR03-IM+I, dZ)%*%rrPK Aorg/PK A org/gradle/PK Aorg/gradle/wrapper/PK Af -org/gradle/wrapper/BootstrapMainStarter.classV[WWd`c@7.VJ -lD!NfK{O]} >i@,֙3}g?p ?(₂LxKE2(UL+!`bցBvdde(¼g(N\n wKb%xW{x_ށe+8 9gX;J$I@Үaji;Ih.UN1]t\Nm^ftʺrg!\[c6uκa}a/&ѝ"EFAC^KfcNPyrw+8 㾅\H(kOİ!' wWC_WLwi6ku{nhwW3zSB.>kVEFbX^'Zk%CZ1UrN 9QЮJ)a8mxwU(ɰT(@,GȨpQUq)eꙔ_Yǒ콋\Tb_[CP]GhoyX}s|K|EhFFSC {3\r(Ij4v5*r]L |jWi X `JŷN=] CAG v-6Jص榈DzL7{٢!͞r+r7RE O:S?{^#I?s &- 0e0NSgg*B' Ga 񙑧3RtGN jcD_I<\?jנVK 4=JO thXhMo3NiL9&Z7 MۖP6( K82$6V]S䡍G L쉱SM3dzĈ`baEIB.ò_hRl?R3cdBr58H2CnH61Oƅ A/N4J q f>=<\5,r}+\!Ƽq>D.r" 'OtLҹ#i1՗~Jņ:{= J[zeRPK A5<!org/gradle/wrapper/Download.classY |\YNXi;ˉKd˒v ~' ~_5xP5/ Oςx_T_R͟ ޏT_uo[|E5WEioG6z/~j;#g&KQ[5E+}G5S7Tjo)nBEL0_YSJ,bI7IU]4:kbRcH"ՙRo2O rYaJ*CVƔ)k Yg d)ME&ɔ[M͔ͦl1vSҠ6fH!M+pθJ9)AM^9&+9{СhWoٺhzn,1OPәL<; cJHh\Qn"JkAuÇENH ēNm=w.uI18!MŒ ApT;ڧ>=ַ;%b~AG,6}1eېיuݱӓq{$(%G8Gy1R*S䒚}7Y3֏&㱉,L T '5XN kI%⎖`ccJ5K)+dIyDNVmZ&ˣδ̮ ;Nn|\VN9 ' Hz|\eLřHO;JNoyNb›d,9֙L+!c"Wڮ)H8JU*PL{Usztڣ{1._YJObH!ml7d!;owݘ`_o[O:$fMwةxn+FG c\9+1$)gCQ]7ɬrR?xE ǛLҗk\g# 2f> [$-6h `V,#o?UiA{JT)aZģ9!pc,*|a5! c^F l-vb+V؆ B+cA]6j3+tӺG*Q9zyU7P;̢:,K֥VoZ۵l+.'WxEdZ5gPAƦYۘ;쒂MuԲCڋ?̾( ܄ٯvug=0SY 2Xkl f._n}p`mؗv|l7h`՞=5a`1udy +?M[3mC[fq˫jVV]ԬU+u=ϡ mˠ&:{I @H}V$h +2h~ Z0 Zn/׽Nuu|U!}/ }万Ќ؉t=.FG13= K/ 8%1WqO 8/,uY< ~*baDRZwGԝx3q J¹'.U68{A|?D5uWCk^OVJ|JK))U!xCήh_'ɍk 735~x@d.%IM Q7iM ] |& ~Lܤ=e-*S*Ms1ܘNasvNߞYuPBlҥ">H9M|/ڛ(+}OI|79t}h$wA'sؘtCtd s=Ľy_ُ`: w46]cvfVL&P)q pq`N4gp$tXOsw8 kd~N W628IW+ҕanah8tJ[^&$OK7FzdaҬ˓,~$KQc,$寳r˷ܷ1jKeFp>cԯE cOa_?+MI:7Y TJGo\H$h*d0;HsGhԉi=7p n]._xoLK6_2^-d*}R|eaLQ~e^au}[O2M4k}9rz~BTbvڞSچd O 4Zo3}a?0$:ga):\hfcDcl U<ԯ!tGX}[Y}ʶYrȟґOkBh„ !*z=?ٍ_a/@W_ńFU`\_MEN"mPK AyL1org/gradle/wrapper/DownloadProgressListener.classu @E+jDE@ۖEERI#3c[>4v9OĪ.r%J[M DŽ,]8kߟ_PU:]3aG\^&at"-EeY˛8\3K tЎBNk؁PK A!9| 3org/gradle/wrapper/ExclusiveFileAccessManager.classWsWYګu|iVMNZ*;JlBNKƎ[t-vjSB[(P`x 3L$x0 }0+9%L=sݿOt]o3;6lKqoF3VB>%lW !8$` Dղ3"x D]AمEU WxcLQV$Cn.O#&A7zx N5@T3(zY4} ] ҳ4?Evqݏ<̏ LNp8>K.1Dg[A|4nkhLpSESv\c~]+蘭vvR5dw=#r<\KT8lo7`.ՐS WĮT U4]~T76v7BZ H ҫ@'c Klϓ31cDQDDwp>Pzp}@8B gmγ*& _$W +kr}FA?~(AZ8:ưq8 ӛ"؅Qc? z5)qjsDPh hF9҈u>c~iMȈvz5HM $?b)nIP$)SݳhѠǧB<q0.Ҷxd(WWw@M߉߭5S< a-sc-gONQM} (1#j R`뛿̀imP/QWM:;"+) Qgc@'Q)f! Ip @"pHwbo8=N%Ťډ;RN 8C?ӕ7oWy+V b3Bųl9ܭ9**$U<~PΫx^Kx{TJZ\/SrB+UtɯRj+akZu ^x 7)xxxX, *xw]rxE?.*>`XR0F|HeqE]LJ冏QPI| g<"9?+!I>//"؎ i?}GwvuDNh걭Xr`V3_ PޖH{[.˲g_W{o:Zbc,7  Z~JĒƮtaTҌ,gRK"54`q錥 VS3=v$%+03|dGn cY@"o-j#f6m VY&협2M-Fފ!JXg4kj5 =/2j&OHnX[\6sZǶC1!ґӟREtk_ڎśNk4"n HezE!,r_M~ֈmrI9 n)\™Jr^PPڬB2Kqf-Inڷkr{%mlmS663o,==Srr^7V'j[&F!T{̴5YrVHL6L2nG`#(DB7-P2&s Nsٖ |YjOS1X; ?5?V ̢CԩD ?B/+ 1kYb63R1Gs%qB{(,2\;Nxau%䋂g^W4Ox l؏!!vB`gSPyw\|w޼=yi7u4WqS.9,8V8s\[>$7{TiWGPY:NFQ7 e?_Fe_Yz2A8FIQrgA(uN#p$9&F9J)2:r@0G>̒RMŀmC|iL u1J/ٴb.%׎rB9,,G oE)2[;nV,ܣtԻ7f:5`jdؐ0[|g[qU:!lɪ6r g6[ aaO<0ùuPNYpiᬎ;Ug$~cO_-|{{ u)Gg>' ݋n9ȠS=.ƲPS9̵qw.prZ1b͊YS=Da(<,`*KPK A"org/gradle/wrapper/IDownload.classE 0  ^b* A{(l|JTf $_uX! n6mla{<}w"MxkC6GeͤlLa3X1V`Ô8rWٻr O6E!1)ʕʕTD rS4>#60>׌q|^6_PEptWe󀂯U|C7cķƷx<`F#ukdtk7-C12h2YkN=ӱG\d^jdJ+XƱK9δR9WZFꄫ ZQ O꛶l.N ,Υ)`& y nYRninK .FY/PQw {,o}yڴ'd2,kyy1,O)6[z`pz'YԚn̛WC VV;1Ħuwp0>m9zGA?jC|8nXֹoҔ]Tr: &Z==35}*xL]=AAWUŁcFFBX6ll+tw@ :St]RXذSt3FpWZ9Rgg,@ ޤU{v [U6ټ5`إaO[4Wד֢ie W# O4LixZ~jxF6?k?dz hx Di>Yz;Œsp^ ~55 ~w«3,ÓqOuY_W 7 lxE^3Atx;-z{h y77 owz, Y2H+B2=uq+'Ԝ욋#2{~^ loXEJȚӒ3#鉯|G?Mo#".@=<]@943+ؔ?*a ֬/m\r1ظrW 4>ph9\=%Wh[]%\CVx<ք֮u=.HHN>DV%S^%W GAw'`X"D/nC8Hi1ų8 ǐxuobg,[AfAvԻ?фx8"NYD"b \#(Wn Ԗ=]xBb c :&(Z2%R)?E*a㙆eU3l? /QR\PK AT,-t+ org/gradle/wrapper/Install.classY |T?'!  $H4 HXe%%μ! j-Vk[-ZתhUP kZܪM֪d #ws?˽My4#)(iFgɑf|uS!*Gn+k.$J3Gnj- knnf4~7MMyJ3mpy.*l9a.vy//4)M&6֣UA-cLnm\v6\)M3Ac<4:(W *-t fwL-O ;+su b_f@|C.b Y04 R{lmz'W KBpGFWy= VZ!+[蹩=jqtu-Qz.X_34lljq4~WUbFCmM)|V> U7*z4ҕ55kCtW1_4nD!(kƃuSBW{. _,Yզn 2|LJȲ4Qģ>0]q-A:ofK h kF<CdcQ 8z4p Nk|B_k~+ $n hn" iaN@8MeだEۙ #J┕alCSVX p* iah«m 5h8ۯu D%7XƗ٢:;fcFzo@]&=lDR1I52"A H$UiT@}^p<d%[(ۓ/o& _w!iJ FLeTf,As6\hѭڝ>k,+N8duΒf4s-[eNɭ2&Tu$4G-9qBOc:F 5Ohsϗg YswY ,>asMV7ۂW&TzQzW^zXTzPJ7UzRr P)ҷ2vU_5|*oPG|х>[TF "Kn\YYjE4Gʷ*Ʒ|%s٠*wQ^4UgrA5驘ʹtSoz=G71(? -j.L"F$ykkD-^8坝URU[T0m:*c" }5Tt+ݦCOnhj*37CO燛͌sBZMۦ{u=5PmoGh+y454ܞmFB]+E7r"# %^- A 1K,D#!5*D0ozAET͏凓+U Y)[i(VEؐ{č|*ܫbGuF. *?Jo?$lF ́p>O!;d"(El WPyZgY)H1=CFT~%KR/Bi,_iSReͯ!H<7(#YzQoK$Zᕨk꠮N^9p@ -l1G`puw%+ Su~Cߩ{?a*T~R6 Ό%J;*+ 5i!uIc`POCbŎW/?ToG|lvrBV6"+ L]26\<&C7._A;A-ˌr#X4/R ĸaXu ;Wdbd‘0 %Ը  f&thaDZK og>~cWB3}fIO^1t WO~ VbI,\"y/9^%"V Y(fIq(qZn5~_IXlH$=dCAawj9֚s1 0<x;4MGzMPi$># eݧ9C[{]O?\:hxuђQ[h;^T},*G#;|r^K'46HEooU&|}z&ϥ4ͨh^FW=nʩpcL=^Tqz%ť=MY@D*L>WZ\JW5AZT4~mX[D?l"休n¬i4~7'݌vkp ȥ9&4Q‘kϺ&z4i=~K'%-BNnI7MSz[r];hh8s]s/O'Ud{i6QFꦓ7x难awQ)_b3ղFϥj4i&(?BPGNh mŌ Bt>E }QTa շCItͧ;'SjXu 匤m?9{A).Ůs)~3:4BSB{|AT>B3ɃPc1AgCLh(=@3fK3r Paq?!h ɭöTE 0ׁbv_.*xho4`bͷ}PbVnrW5'=#jȦ#4]SK'D| :&jJ*̺R7QLI(mlrz"Yc/Dη{R)2| 6A`Ա(Ĕ߹xY\iz}*=XMII_CKē̷LߌooLqz"!xWB8)1xT4Z`-p oicN;I-8В,ڰxzSL;a\~@`\N}Jʄ-]/JY9j"Ф|P'J)~ _clNE KyM9K{zneMGɖͩ9a MV6Rm|CgPDz(B jp=My%gwڀx$dM.d]WD6H \!bKMxNn nM`f쁄h>u Kyh)Aʺ3vSrD PڃȴQ!nhp`0àpsivrY%t934d: z^+Lz+0e5Y_WL8N00)c96r+iyThB)Rz#4}}'-W /Do×ẍ́-IK+wu'9mSc$Xb0Q8BB FL]:^8Ȓ"x.,6= z%M',<!a۽&ކYf al< ŋp9О8cObª̠7-S);,?vs<3ɒ6el.nuM/Jfn`pd^2 (DCn/^v8Mz(C1*tgᖫm(N6Nq=BnB( KwR lqC5 1ކޡS!2z?>DF>F,>>ASkt6 mBa >;Cg)e_VtW˚S~Di)(>V+٤\FЭd|FY}#5P,[$3E#'+)nF5eWCq)ʭhDIYluB֟\hST{FŋK@ )Mc=&1S͢!#=B(v4t VbpWY4h൦g 10+D*w0n9p92!83i՚`//bq-|N,H,Ye^m$gJ*%d-cgGBͫ .۞͕%pqAVb4 23+6_nΛ p63)3>2(|VQJBGPK A:o4org/gradle/wrapper/Logger.classko`Unc@&s*]711$KH`wʓ_OFg ?xR5Krw.??hG b1TP4w+ͶU].;`XxfX!R9Ӳ!1,j<8>?4dckqǐ{0#bvtUwxQ; 6m!W\5]1,)@F\s ˵w/'.Hqϰ3:NWfu-Ce"!lU#;m"x*@obw=Cj[$B# %qcI![3̔JgX&ovHIFi QV(Iؔ)r /,*ꊧP*qw(P&n_ݖ7ۛPK Aon`8org/gradle/wrapper/PathAssembler$LocalDistribution.classR[KAfV㪽K>ERPC&ɐL\wd BJLB1V}3'}ḷ%xX3Kc^xBjW}B'EH%t4˻jt'hNd|E/uE` ϚԌ>T ihdmIXlTϚR $%'I%,!ת9UOi*A"[͔~[ؑݔ]Ouw%㭚P8H .@ \s> X)H;fOrBfVY5 UBe#Vxxv.|D#Pt '^sazO1HPL4bg8zձaXWdm WivDPK AJ[&org/gradle/wrapper/PathAssembler.classVicW=cKYǎb'c1, 4@5Qk[q[yyF e)})P(C]hPob;wf,ٮLzᄃ9wy??#r-c=#nȐaC%YU<A9ٱE*\@Mپ%æ|R0>t|VgU|NGp_ᶊT<#Ka|Y"WDoM a|;ໂb rE/)8:]Xfɱղc,Zڲ {"JFIscS+Ss+f3S+ s陋 z*[< XQm薳ˆ#fX:lX,†hxfBa3oDA2 K ,ڧM˘)o7_/)k3ଛd?]s)*u֋EN]֝1zAM@G=g8od1o\EwtmQp^+ i ]Ҭ'څݰ*pKW̢[.lyl/uJ' TsƤ3J>OdmJeM#tu\BX\3~|B%v#BiMcj1FKat4cW~pRsCB ]զ"@DhwIsx" 9B^3dſF䄆Q<8&񄆏cVCӼ{-k^Ѱ5,f>k~,:?Oj? ~W}E/6~f0ˋ|@ū~j~Nm\rP(b[輦X+Ε-0;Q(1Y1*W*#bt_;hw.v*835_Y~3]-dM[v$AU*|3Ku*"ߎ3׍5gּ_z@wk3ް*$/PVV;~Is >>ГZۘ_xv7@'O+D}vJC Yݡ`0 e}P$56gKEӍqU`<]rJ]`C,x\5aY'c{"LJz?gs0Qzc3ЇG(i>1b`705E7";h[9BZwU4[Z:iDZBbI|;@&1TEp&1"t>uY WѲr\iEpp]ݣtt]i~(cˉ`w;=qӕA#a׵Kk1V .2M@Ce|y4,ތ؏`eU8M^g2zz_F0lmNQ׳GidYK;[CIJR %><)6{2C } g:ƆVK9#]Q۶͔nv-mνv^g-*6`Ja#Y" GAN l-|,g+[ *DŧL縥 |+||+Xyvy)'1MnBʶ6w{/(X,(~> Wٹ## I=(DWF$v t$0;/~*xBDV` -n|/#)yeǤ2FIi&^ʫ,=A5ٶTmMfRص/}6-ƷbU $egRevX|3%_ ๡~cg5hOW -a.5T cO_ {LP; e3y؆:J{3Pw@y42ESp~Gw"03V;LM`q=4/Z>u`iN]xG7Y κcA=#7? I4lv14$ ĨnqR!9KM-z9BԯrW)5" ,9z|~_=/!~L08WIH-_{M F1WU> =SpL<`ݖ_bqWPK A=?-org/gradle/wrapper/WrapperConfiguration.classmOAgJK|i " HULCߐ-H&~*M$&3w e&33_:a`@EG xL<2O<%xN8mPk35 QOM5)!Bw~+ 1sM(/;0/w^9sܰ nZd,8t|ZkZMlONlڍiv,.smns =NN8u ѽq$&L*A=HL)BCO*A4dF r_ s )%Ƞ 2)AeE, $!X yw y%^}93 2y~Oȸ`;)H^V0YW^а;98147243Ot KNj-;ޞ-#;[N3}Ht e]rbbAqy1ypȖmGCN$*= 8%g9ݲ =/az629uȐ Nl=qԤ1.aCi[Z:k?̝`iafRݘizoX4֔r!vSF`N3M-1z_arTQ5c!2xݮ\)&* ԉ^-ޫcd {Zn! ]$E锞s=' r|˝4g9yJ YE n ts@fJBU(E2DK2t!cj'-BFY&v\vwdLmz^B6i5~g#M ;{,5;UkUD u=*$$)-^QI?dIe ͞P#1F/Q0'i?e6!#(莄1eL%|%y,dKܢ"|j¡SRqm5U;^GQ˚h&}#Y܎I7w<}EA'LQQWMUόD2 }ʉx>1COG)7raWTN{Rӓ|88aAXTYoe݂zfuytR{:v:Z|`G_8檫x8󨊣~̕7:+x@-I :bqJ޻q(Kq6۷bj &};dm?JpE)@a ڦŕfhr%Q2&xglL->lDM6uFgºߏ C!̣Bh^GЮ hϳ_F~;=U7Ӿ˳_0kZcz8Ivzv0ixUñp,sϢfa\s oе(C BbjJ%%@,,V.ZX@3#8ꚑRM`:BBNcX@ xe,^F88isO[`IQfQ?b^ Ϣa ItV9gw"3X6;kcs9['_@cp qvC,bW/\ťl 9OC(.H']T !ٞ ތīS]hDLyW!p 5 kN=NRnp؜ch⟐ϔ4=c/-ePK A׃X ;org/gradle/cli/AbstractPropertiesCommandLineConverter.classV[WUN20 HԄKKIQJ;L0fOZZ_tA}N.i2Y9};vO6Q0e|`|`w,'? H` = V>Bx&c.cC i?]cЗ1-ci8"qB[׊kcrƔmeBhЋfb~MVd8i ޞf'$ F]p䙶0fv}-QԬB"9U ёѻE#0ff[-PvT4V5%\X3LXQgIWW]p0?:ĒVJFOMA`i ҮqA1\W@ \A܊A)5"ɓ48,FhJ+g ^zKŽa@7e2ZfYTRQxuWx8R E10ogm74Ӂr_q9\WOw/jhz"#z,Zi.ZFkP*؏$}iB+ c na]bᶂ1|( 2>R1>aʠSz5 xA$>UDP~.*8 %>Ä;g+ZEkߌM' g6-0 : NVϟ=!!{LX`e2zFI3U\%Ne5CC]Z]AၺmѸYCYbZ.+&%b `)s4 "(({j^<Q*>\{#%N׃\&9I9UZ;;:"@x°v.UkʮۤXRbI3D -k|Z*tzDB!4q< bALC[j]yƖ~D=' * f] Lrs Z(ܚKL=VML̖lc:N>}PWщE(QɊ$Uio馥U1Q>1r˫b-gq:ڻf9cЩy{բ:9OR/iPFFzPH 4mi^ڃ'xA3 B&P&`Sh!^ Hp)LcNG{&ſƃ精.R$(A.%R,N`~vXlMl,݉: A&CA' 7"!Yr8GR (6^f"pfSQ;!neGl=Zs> wDO7Rx0D!o)<=PK AD&3org/gradle/cli/CommandLineParser$AfterOptions.classmOA{-r- >W+p"D!$MFxag9.D%2^rҒcffwn׷fqۀQiu4h IStLaTzj6Pɓ5&yյXOlե}G8]x2Crɫ< +M[>.YN w\:JIi0dmxBBr卆Mu0r$fu~^F+[.5k՗-o0$z<AekͨS bVgcg>v@]7|- ƪ-+CG@ϔ0 jE7 7ckމW7xؒ1f00yd835?UѶ= q~ :5hhkmq_2wC^2 \ G@I]TGi4gL,~AbT 4"A;`ȑm:C٤3qhboPK A <org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classVRF#ĸ5|ܒ`$[qpZ'&Bql9#M^зHg!)Ӥ:ӷ߾C;=+9`bL&3=o?=: sx c'葑"GN%Y\ r|$+ 8p㦌[D82X(pa跿3|ݪ+UZHk5~G#ay `V[:)aXoʺuW-W5ZXY-a5bɠ2MZNEOAmEγ0 ͢ZvmMݹ6m9~YIm0+N˔7Z!]?vuO"wtIUh8*\Xk۷G(2l>¬{'31+s ^cQΈL aː:{ 69 Jdz>dxFgnfQ.nOO_<܁'Z=O=6> 6L{(3jK6q/G H}4"Y|Gw! <@)|R JTB;|pI^!yJ= Nt3D5Q[B]F]qšۣcD[̦hC#I>GIuM; Dm@XFٜ8BsjO;9l/tq иBjQ|,1%MgyF  U^9ۄW4~-PK A*ZMForg/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.classS]OA=wPRˇ"UhAx1MLԏvn/`|EkC9{Ng?&6 Q)`,95=K&lfc*!|m2]Bt%a||ߓzGy)vV&+"M?~"u$ۑV~Q Nnx" %6m܏#nԍ֛uB_Є"[f)ְm*ȧHjfp\p ߩLbs E"Ld'h@Kӟ0}1/d MXEnqsYX'>9|r9\=wP5oy$L̑iftcye}ly:E1k-LYn3q2\uM&:c#2Oȭ㿈(&J`R؁p6k0,X\*wM/PK A2 =org/gradle/cli/CommandLineParser$KnownOptionParserState.classXwdlFMHybژ6 6;n63qf6 ZmQjjikRUOn]~uϻNL!!1eLPB2a F ACaÆD01 BX'x*<3xO a7~ʄ? y E>%^b֗%"Uqtw,HHx0;gahkՓTm[#hOXj<ǒz{9<nhT֬w znC,2">XJlGu4 ogB?# :MU)eE:=m:);퓪h!ݮ= znNž/9i@ c[˘$ޯYITF̘P->2acg՜hn*l@~Vm4DjX3{sմT ya`:n)B6)ֹ49T;{ƦHRc/)L`:C/=y gz`9B›ޒYYzE祓 l6.)+m994m52qCX,ݖGe܉M2.e<dl2hM2 &\:Po7(qStG=)b6w?Ȳ6oBm(s(æ2bz\+6 d2v""2N"*wtyn۔U^ЕQ6FbS8-=㌌?਌?r$RIGz̈1,,$|pn׽‘q1"PɘĔ߱ t.0-σk]ThYLu [X[^GTǴhJjm!Ԝi-Xԫ7:{# QaRobf$!WW/͇B<4NIs,3QhJiS`;r5ln= ֕y<9R9B=rZ:OS+g_kң֟`Yؔ*\f,grzs:I4 Yؔx@нA=s(lNpEk}'})TM5ϠZ`K.b ssXʎ9(cW owiBHz:DA_LlJO _[f9&#xFz]M&8vtP ]}-3Vp5:3S?CݐkADx:nq +eO)Q9T&ė8&KB|+䓷) wQq=org/gradle/cli/CommandLineParser$OptionAwareParserState.classUn@=q$6\%)MK@)p)E E*oĮO x$ J|Mݒ*A./ޝgf퟿PĽ8ȩ0*wTzc\ *L+(cVAQu4ܮ,dȖQ/5̂Ѱ OpC{i\e˶; ` CdթQIh5xƫ 7*\X.Cɶg9Zŵu6jI,s]SMj%} P녲',4!E]&8c$${]pG짍oRNK%ti!ӘЏSnbX[XPa sLf +~a[f:~Z)9hOS csmqr |FdUԩ0L-=ƽ_qkޥvrl0.ϥF|x!JӚ'vt!}rOYY,T6$a|iZ ̋dKTTȇC(Z7D!eSZ2B#oo+5UcCݢ{ B*^v#8GNi$y6+1E83$r]oPK A%̻7org/gradle/cli/CommandLineParser$OptionComparator.classTmOP~Q: 2@.,Ydďe4kI?/~#ƨ_ N6).]}s=~ E%d0#0+bNUJ"E,IHs;'"V8|USk"z6L7eA(;íi;- Vn)L!{䛎]vG Wlp˖y!P~`j2U6uyN_z`QWkH-T T|%|4y`P?UKjwMkwuz-֤$/0L[3xѪM7-O7 IRiu;?ڑ~Sb@ZaBhΟ\ia+6eYgљ{"!c /&q va[hǂZ00 }m j]{a=eўB$>P}4s2|=ѧQ*te躣K.@ >rd d$S3gH|$%!zp'a!xD"2{9 O蹀Sp HswnL8trI"!y3Ⱥ2GYv>i<2<l4!M{nV  #fdY"5>{}FCNS#ZOqϣHINQ2(R8˦Sqv[lB|'9乎OE;McBһ-!%."{N'MzzY%B65[m~kETBZƓq5<]/h}LѾ>McGMHx)PK A`M~U2org/gradle/cli/CommandLineParser$ParserState.classSoPN) s97ս&MLf.а.vF'_|(- AGmdQC-6xbaB{I/zI4\jϓdbs ?4iF^H(*tU?'tUav/Pcgw9`2r;$uTyP/#}@3I8c)O;B / Z &Wti2qfYC!zPڕh&ߗP2egvnӁ$$T@|*>A%W|):T Џ3_qI_q3!Źt^= xc @C!:Z_ eYq>8YMHEFw@@9\"!vCz1v񫮥x&҃k$}ˌf!uTsj]p99+1:*4*4fE!./1Y ?PK AdZl)&org/gradle/cli/CommandLineParser.classYi`\őJ7zzeٲ=`l1S>K6XzFψ8B``d MͲaك= !l~ޛPwOwUuUuO{YT:jW5ױh/>)s3 O >ס yRa#||1ׄW%GģcxS5E]%_fFeu֤Pt|e&cuq8&&䞬JO|7#P"tM$(L8?=cq3֔&LMssOA0eAQC(j]Z-um 3f5if ≦mkG0JKͶh̚dcu;13cM0[1׬_ݸa5u֭X( ^N1U&VQQ[٥=IҨ]k G-\FګmWEc`kجn V"E9:Gw6v1|yqe41P<-l҉H(H[Rs,Jؽc[-`,~;DG|Kglloi5M% 9.bI+v"[FURo;R`FN3#mL= 4P%$lu * cLate+r"nuUCiظ̀J]B\ kX5Pj:)Bp(^Hi%n Zkn ݒ_>N &3A32g R4d Z8?lyOm'ˆf@hՌ%sƞUu63iʭ ŕ%p77DL^aE9͚V\EW p vX8)4iFf(Ma}.l?F,N@6 7w3§E5Fp J-fn1R^:t[BYԙd3R÷M΄A-Vvmϼ.(SYnZQ_;S[Zx|ڜ3KFR^9fpUg sPY1O/ }MX k#IRr ܊[ ܀ ܬFD- ;&-i{OP<1Mڹt\͐׍ku;5nHXv!]r1% 0Ґt *1T]Bحt-씸!ǐK2C.+%ª2C!W*or\MxղZmU3Wq\lE,rRz[UV3[r!7(G(Wr|ېjCn*%*Ų!wYX2u]4yӇY <'kP͝%w't3luY9LُC'dR{23$* 0d\/!{^C/hr7ܟŞkCPɈ: \lȃnяEb`*ƹc&{>Vi%=f ٽwbeic^Rĉ^Éww` OF3<,dn>g?_y2|% zX>"Nd1VfY72pLbh1s}6=JqŴ*9DuXUǻ?}e[ւeN(q%B=:FsWz~-)u+Z v{p,|{`8E< r_n۷Cc^{[܉բzv 46<[]kt6SNo;:ԃCqֻ[c`|ݽ(~zvV7\e"z>LP_kp6#+Lh1I`E4c/]AinعnV0=tziH_r3 %?~u'\vB A 7o}mh~ ǡWs _&%@,yő<ހ M3y⼃N wnW})m^YAhO YL+,l"G˱7<7hb>xi!_ph 9Q}( a`F˜Zoeۋ局v}r8i7N"eK{1\NIAU[k|6e)=LgitE:Rt=("4RA~?(N{,$)>ȡ)Y>gGK;Ȯ,J͡%TZX֋rE\ދ O܍€?i.UMj[W\V *Rv"uGYxm;>,.ӇK֑lwlfe/NoE'QbWb#`cm3< ؊_"K *#`x)hbtH):Ll&evH'҅.M^Q~;9˸T7C\)5?z9sr*hp?ۻ0=Q֜F {twtc1~DkUa!t0F!SE/wXS'Md_ø8缁羑gM'9K (=SX-,3,-N=uS9Pi Qc"%p;°s`qx<6V~,z*-wFG|:%f)XJXBV4[J^ ϑ^lT{ pg9܅*+/#ߒZJNxy*uìR6+|*,&VUV} 5^ƇbiҕbYЇ5y\$h:4"i4hpm7H8T ^Rx 0K%kAg鵓r7s~!o_ǜ9`9_K_$,+ J;~);܆%!Myxw#){9%qG2wR0 /r5{,5qBH\ d^pKPΓ7xY+b܋7X:yxY絲F园ɯS-18gO{zSe yNva`aZx 5mCd"QLtLq:ɛ ec%,3w]}sS}~e?2<_p媲>lJ0ݩjA^i uoQEpê8~?oSw/-Oijwg޶K/UGy^}B,ZJ,;;ɢxbf9rKa2J|ߋs=ijS8TPqhQnsʃYQU@O~lm.I=oA`2/-'a*o}CӑMswōiV*,K:&U@cHb{V5kyE=!#&P== kOц?r]?1>gAy{8u ca*^H*R!Vg-yh.#fN>_{EV43$ffN8Ѭ;ldO sN]wai ;{g>.axtv2Ώg9+#_;q eV)^?PK A>&org/gradle/cli/ParsedCommandLine.classWiwg~Fċ%vTMc[R8S)-LT(.Ph١li7 `rX;Ɵ}g$Kָ1G}.3ǽ?.v*`!*΢ .bufT,.+*WBM0#h'".T=^a}:|Fkt 0^7/㋸$__V0AVMa q[ ͼ1s#+3ɥ/E; f2n-C#2iҖ U0RҒKMfr)y(Q0r*T>c4yZq%sH˶YhM-C#\U08a~.k *)CxK )LAt\гkWYp#A͙ FA|Wݳw/뀽)xV5KԶx:ԕ|)#wOPccI(V^yU6KbѴ\j3TpUG(|VQH1M 7S8 RΊ|{Y#۶nQ/5^kKouO;=Fm,Rhq35$bwcLOFܙm Ln"9mG7Mhz*gJwrv詔DճEc YeyK?a{?՜qZ:fyȌYcm5 ^Xdkޏဂ6Y"|P[x[w= 1s=>4?RcfUDO38*$c/GW*S.5“~Un |ɘ_=0a 4 WU\0~pWLHZϖ:zypy*rK}jc븪֒[v.2}Ric9SVUPPIΝir+9gS QZyۇOBMkI'ƠG> =7rW=¶~̜gD1[f(O :6yP=𸟳J8Je2msQP0-^^Ц5[y?AC2?TjH܆mo"@1H1tXG1r}kL%װCРh&4o! ;]LHҰe(=Z[];7d?k'Wo A؅속=x5:ICab!Zcx(Dp1')1a8!N**&T=thT_P;='X/ FΙbX@u #Bwvp\}b9ûx?}dT}HH.o!syVOCI/a$qaxA1cx)R_J@{& (+}?Av3xG f97CTEB"]tF.'ޜ軅؜t<õ2i 1i_3%6 ;Aؓq6A-V4RgZlG orN$gdyE:+N:$̕ųxU '\5B%ǻ6 Z3]^ᜐk>lJ ;k>e'*6zEGe)A<],;[S;\Or=l8>Y ߀^9ي NLvczͭ&@S܇Қg\HVvWc .97{XŘ㰗Go )ȑ,I8sQHI 0$Abs9{`_i*^QUt  9%<' tEB^Krvs?`A^EAEXP QP dȹPK AytE,org/gradle/cli/ParsedCommandLineOption.classS]O@=ݯGePaeQ"hHV1YawRlIgN[`Y$ә{=?“4(H#b 冊$4-L%q[器+r⾊ [lpWAɶ(Ha1p#-g,C/{9*I Kxs UEJ%a:w^u"]a*s!"k~E쳟}V_*bTG;-%bXo"p(=@&_2w%^*$APPS =1D:!䉩If%ޱn05W(vbRD $"xj2Dϧxr7k> !V.p].GӱD\8"y RPK A\vB| :org/gradle/cli/ProjectPropertiesCommandLineConverter.classKO@D|?Pâu#Q+$C;1m  JW&.(1D,9vo/[@yl汕G)v }FHWkwLS!]nY7ZK:̿cJDZRysV;H+-)nkS#cruLXgh|BjFYDΏ%L%񎅎*_?ֈ:("<ڄbJՍ ؊tf^*K ߵ XUVi01k p8wZ8T0g?PaΛm=C Ss | 1\Zq-}C_JEˉjE+ w'PK A 8=|9org/gradle/cli/SystemPropertiesCommandLineConverter.classJ@ثmjE5BPąR/P~ӑ$&BJW 'iAY3͜l "lYlE <& d@HgL{:rRs:C*X4NĬQ ۴;hZ3a ѽG!]Gv7S"5eb o}ɸGtFMz9y~X{()spL`7e.KV, TXxɢfDTEGPWJmh~49AjxѰ sh gԙn85].FԒs9Q΢*s/@Ug J*ce+s+1 $p6/t-,;h-.Z >kZPK A?gradle-cli-classpath.properties+(JM.)**+MPK A%gradle-cli-parameter-names.propertiesPK A AMETA-INF/PK Am>=@?)META-INF/MANIFEST.MFPK AAorg/PK A Aorg/gradle/PK AAorg/gradle/wrapper/PK Af -org/gradle/wrapper/BootstrapMainStarter.classPK AhQ}#korg/gradle/wrapper/Download$1.classPK AL4Norg/gradle/wrapper/Download$ProxyAuthenticator.classPK A5<! org/gradle/wrapper/Download.classPK AyL1org/gradle/wrapper/DownloadProgressListener.classPK A!9| 3org/gradle/wrapper/ExclusiveFileAccessManager.classPK A,y- org/gradle/wrapper/GradleUserHomeLookup.classPK Ac67 *u#org/gradle/wrapper/GradleWrapperMain.classPK A"d-org/gradle/wrapper/IDownload.classPK Ap@c "N.org/gradle/wrapper/Install$1.classPK AT,-t+ 5org/gradle/wrapper/Install.classPK A:o4\Jorg/gradle/wrapper/Logger.classPK Aon`8Morg/gradle/wrapper/PathAssembler$LocalDistribution.classPK AJ[&Oorg/gradle/wrapper/PathAssembler.classPK A| 0nVorg/gradle/wrapper/SystemPropertiesHandler.classPK A=?-~[org/gradle/wrapper/WrapperConfiguration.classPK AG (y^org/gradle/wrapper/WrapperExecutor.classPK Ae #ggradle-wrapper-classpath.propertiesPK A)4hgradle-wrapper-parameter-names.propertiesPK AA}horg/gradle/cli/PK A?<S1horg/gradle/cli/AbstractCommandLineConverter.classPK A׃X ;7korg/gradle/cli/AbstractPropertiesCommandLineConverter.classPK A}yGK1oorg/gradle/cli/CommandLineArgumentException.classPK Ag)~qorg/gradle/cli/CommandLineConverter.classPK ASf g&rorg/gradle/cli/CommandLineOption.classPK A튯($yorg/gradle/cli/CommandLineParser$1.classPK AƭN ;zorg/gradle/cli/CommandLineParser$AfterFirstSubCommand.classPK AD&3}org/gradle/cli/CommandLineParser$AfterOptions.classPK A <org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classPK A*ZMForg/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.classPK A2 =org/gradle/cli/CommandLineParser$KnownOptionParserState.classPK A$ľ<org/gradle/cli/CommandLineParser$MissingOptionArgState.classPK ATK>=org/gradle/cli/CommandLineParser$OptionAwareParserState.classPK A%̻7org/gradle/cli/CommandLineParser$OptionComparator.classPK AfC8(org/gradle/cli/CommandLineParser$OptionParserState.classPK AE3%org/gradle/cli/CommandLineParser$OptionString.classPK AgAqx=!org/gradle/cli/CommandLineParser$OptionStringComparator.classPK A`M~U2org/gradle/cli/CommandLineParser$ParserState.classPK ApX k?dorg/gradle/cli/CommandLineParser$UnknownOptionParserState.classPK AdZl)&org/gradle/cli/CommandLineParser.classPK A>&org/gradle/cli/ParsedCommandLine.classPK AytE,org/gradle/cli/ParsedCommandLineOption.classPK A\vB| :)org/gradle/cli/ProjectPropertiesCommandLineConverter.classPK A 8=|9org/gradle/cli/SystemPropertiesCommandLineConverter.classPK A?gradle-cli-classpath.propertiesPK A%"gradle-cli-parameter-names.propertiesPK33ggradle-wrapper.properties000066400000000000000000000003121455764576500400450ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle/wrapperdistributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradlew000077500000000000000000000135101455764576500315330ustar00rootroot00000000000000#!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed 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 # # https://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. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin or MSYS, switch paths to Windows format before running java if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradlew.bat000066400000000000000000000055761455764576500323120ustar00rootroot00000000000000@rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/settings.gradle.kts000066400000000000000000000000561455764576500340010ustar00rootroot00000000000000rootProject.name = "gradle-kotlin-extensions" junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/000077500000000000000000000000001455764576500307475ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/000077500000000000000000000000001455764576500317265ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/kotlin/000077500000000000000000000000001455764576500332265ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/kotlin/com/000077500000000000000000000000001455764576500340045ustar00rootroot00000000000000example/000077500000000000000000000000001455764576500353605ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/kotlin/comproject/000077500000000000000000000000001455764576500370265ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/kotlin/com/exampleExtensionFunctionsTests.kt000066400000000000000000000033211455764576500442550ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-kotlin-extensions/src/test/kotlin/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.fail import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.aggregator.ArgumentsAccessor import org.junit.jupiter.params.aggregator.get import org.junit.jupiter.params.provider.CsvSource import org.opentest4j.AssertionFailedError class ExtensionFunctionsTests { @Test fun `assertDoesNotThrow() and assertAll`() { assertDoesNotThrow { assertAll(setOf {}) } assertDoesNotThrow("message") { assertAll("header", setOf {}) } assertDoesNotThrow({ "message" }) { assertAll({}) assertAll("header", {}) } } @Test fun `fail() and assertThrows`() { assertThrows { fail("message") } assertThrows("message") { fail { "message" } } assertThrows({ "message" }) { fail(IllegalArgumentException()) } } @ParameterizedTest @CsvSource("1") fun accessor(accessor: ArgumentsAccessor) { val value = accessor.get(0) assertEquals(1, value) } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/000077500000000000000000000000001455764576500273775ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts000066400000000000000000000017451455764576500324650ustar00rootroot00000000000000plugins { java } // grab jupiter version from system environment val jupiterVersion: String = System.getenv("JUNIT_JUPITER_VERSION") val vintageVersion: String = System.getenv("JUNIT_VINTAGE_VERSION") val platformVersion: String = System.getenv("JUNIT_PLATFORM_VERSION") // emit default file encoding to a file file("file.encoding.txt").writeText(System.getProperty("file.encoding")) // emit more Java runtime information file("java.runtime.txt").writeText(""" java.version=${System.getProperty("java.version")} """) // emit versions of JUnit groups file("junit.versions.txt").writeText(""" jupiterVersion=$jupiterVersion vintageVersion=$vintageVersion platformVersion=$platformVersion """) repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() } dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:$jupiterVersion") { exclude(group = "org.junit.jupiter", module = "junit-jupiter-engine") } } tasks.test { useJUnitPlatform() } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/settings.gradle.kts000066400000000000000000000000531455764576500332150ustar00rootroot00000000000000rootProject.name = "gradle-missing-engine" junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/src/000077500000000000000000000000001455764576500301665ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/src/test/000077500000000000000000000000001455764576500311455ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/src/test/java/000077500000000000000000000000001455764576500320665ustar00rootroot00000000000000FooTests.java000066400000000000000000000010261455764576500344170ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-missing-engine/src/test/java /* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class FooTests { @Test void test() { fail("This test must not be executed!"); } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/000077500000000000000000000000001455764576500261475ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/build.gradle.kts000066400000000000000000000017531455764576500312340ustar00rootroot00000000000000plugins { java } // grab jupiter version from system environment val jupiterVersion: String = System.getenv("JUNIT_JUPITER_VERSION") val vintageVersion: String = System.getenv("JUNIT_VINTAGE_VERSION") val platformVersion: String = System.getenv("JUNIT_PLATFORM_VERSION") repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() } dependencies { testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") testRuntimeOnly("org.junit.platform:junit-platform-reporting:$platformVersion") } tasks.test { useJUnitPlatform() testLogging { events("passed", "skipped", "failed") } reports { html.required = true } val outputDir = reports.junitXml.outputLocation jvmArgumentProviders += CommandLineArgumentProvider { listOf( "-Djunit.platform.reporting.open.xml.enabled=true", "-Djunit.platform.reporting.output.dir=${outputDir.get().asFile.absolutePath}" ) } doFirst { println("Using Java version: ${JavaVersion.current()}") } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/settings.gradle.kts000066400000000000000000000000441455764576500317650ustar00rootroot00000000000000rootProject.name = "gradle-starter" junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/000077500000000000000000000000001455764576500267365ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/000077500000000000000000000000001455764576500276625ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/java/000077500000000000000000000000001455764576500306035ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/java/com/000077500000000000000000000000001455764576500313615ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/java/com/example/000077500000000000000000000000001455764576500330145ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500344035ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/java/com/exampleCalculator.java000066400000000000000000000006521455764576500373420ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/main/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; public class Calculator { public int add(int a, int b) { return a + b; } } junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/000077500000000000000000000000001455764576500277155ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/java/000077500000000000000000000000001455764576500306365ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/java/com/000077500000000000000000000000001455764576500314145ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/java/com/example/000077500000000000000000000000001455764576500330475ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500344365ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/java/com/exampleCalculatorTests.java000066400000000000000000000022271455764576500404200ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/gradle-starter/src/test/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class CalculatorTests { @Test @DisplayName("1 + 1 = 2") void addsTwoNumbers() { Calculator calculator = new Calculator(); assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2"); } @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({ // "0, 1, 1", // "1, 2, 3", // "49, 51, 100", // "1, 100, 101" // }) void add(int first, int second, int expectedResult) { Calculator calculator = new Calculator(); assertEquals(expectedResult, calculator.add(first, second), () -> first + " + " + second + " should equal " + expectedResult); } } junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-module/000077500000000000000000000000001455764576500270445ustar00rootroot00000000000000junit-jupiter-api.expected.txt000066400000000000000000000010541455764576500347060ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.jupiter.api@${jupiterVersion} jar:file:.+/junit-jupiter-api-\d.+\.jar..module-info\.class exports org.junit.jupiter.api exports org.junit.jupiter.api.condition exports org.junit.jupiter.api.extension exports org.junit.jupiter.api.function exports org.junit.jupiter.api.io exports org.junit.jupiter.api.parallel requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.platform.commons transitive requires org.opentest4j transitive qualified opens org.junit.jupiter.api.condition to org.junit.platform.commons junit-jupiter-engine.expected.txt000066400000000000000000000010501455764576500353760ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.jupiter.engine@${jupiterVersion} jar:file:.+/junit-jupiter-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.jupiter.api requires org.junit.platform.commons requires org.junit.platform.engine requires org.opentest4j uses org.junit.jupiter.api.extension.Extension provides org.junit.platform.engine.TestEngine with org.junit.jupiter.engine.JupiterTestEngine qualified opens org.junit.jupiter.engine.extension to org.junit.platform.commons contains org.junit.jupiter.engine junit-jupiter-migrationsupport.expected.txt000066400000000000000000000010641455764576500375640ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.jupiter.migrationsupport@${jupiterVersion} jar:file:.+/junit-jupiter-migrationsupport-\d.+\.jar..module-info\.class exports org.junit.jupiter.migrationsupport exports org.junit.jupiter.migrationsupport.conditions exports org.junit.jupiter.migrationsupport.rules exports org.junit.jupiter.migrationsupport.rules.adapter exports org.junit.jupiter.migrationsupport.rules.member requires java.base mandated requires junit transitive requires org.apiguardian.api static transitive requires org.junit.jupiter.api transitive requires org.junit.platform.commons junit-jupiter-params.expected.txt000066400000000000000000000013011455764576500354130ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.jupiter.params@${jupiterVersion} jar:file:.+/junit-jupiter-params-\d.+\.jar..module-info\.class exports org.junit.jupiter.params exports org.junit.jupiter.params.aggregator exports org.junit.jupiter.params.converter exports org.junit.jupiter.params.provider exports org.junit.jupiter.params.support requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.jupiter.api transitive requires org.junit.platform.commons transitive qualified opens org.junit.jupiter.params to org.junit.platform.commons qualified opens org.junit.jupiter.params.converter to org.junit.platform.commons qualified opens org.junit.jupiter.params.provider to org.junit.platform.commons junit-jupiter.expected.txt000066400000000000000000000003741455764576500341430ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.jupiter@${jupiterVersion} jar:file:.+/junit-jupiter-\d.+\.jar..module-info\.class requires java.base mandated requires org.junit.jupiter.api transitive requires org.junit.jupiter.engine transitive requires org.junit.jupiter.params transitive junit-platform-commons.expected.txt000066400000000000000000000023471455764576500357600ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.commons@${platformVersion} jar:file:.+/junit-platform-commons-\d.+\.jar..module-info\.class exports org.junit.platform.commons exports org.junit.platform.commons.annotation exports org.junit.platform.commons.function exports org.junit.platform.commons.support requires java.base mandated requires java.logging requires java.management requires org.apiguardian.api static transitive qualified exports org.junit.platform.commons.logging to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.runner org.junit.platform.suite.api org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine qualified exports org.junit.platform.commons.util to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.runner org.junit.platform.suite.api org.junit.platform.suite.commons org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine junit-platform-console.expected.txt000066400000000000000000000012041455764576500357360ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.console@${platformVersion} jar:file:.+/junit-platform-console-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher requires org.junit.platform.reporting provides java.util.spi.ToolProvider with org.junit.platform.console.ConsoleLauncherToolProvider contains org.junit.platform.console contains org.junit.platform.console.options contains org.junit.platform.console.shadow.picocli contains org.junit.platform.console.tasks main-class org.junit.platform.console.ConsoleLauncher junit-platform-engine.expected.txt000066400000000000000000000012661455764576500355510ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.engine@${platformVersion} jar:file:.+/junit-platform-engine-\d.+\.jar..module-info\.class exports org.junit.platform.engine exports org.junit.platform.engine.discovery exports org.junit.platform.engine.reporting exports org.junit.platform.engine.support.config exports org.junit.platform.engine.support.descriptor exports org.junit.platform.engine.support.discovery exports org.junit.platform.engine.support.filter exports org.junit.platform.engine.support.hierarchical exports org.junit.platform.engine.support.store requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.platform.commons transitive requires org.opentest4j transitive junit-platform-jfr.expected.txt000066400000000000000000000010241455764576500350550ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.jfr@${platformVersion} jar:file:.+/junit-platform-jfr-\d.+\.jar..module-info\.class requires java.base mandated requires jdk.jfr requires org.apiguardian.api static requires org.junit.platform.engine requires org.junit.platform.launcher provides org.junit.platform.launcher.LauncherDiscoveryListener with org.junit.platform.jfr.FlightRecordingDiscoveryListener provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.jfr.FlightRecordingExecutionListener contains org.junit.platform.jfr junit-platform-launcher.expected.txt000066400000000000000000000016531455764576500361050ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.launcher@${platformVersion} jar:file:.+/junit-platform-launcher-\d.+\.jar..module-info\.class exports org.junit.platform.launcher exports org.junit.platform.launcher.core exports org.junit.platform.launcher.listeners exports org.junit.platform.launcher.listeners.discovery requires java.base mandated requires java.logging transitive requires org.apiguardian.api static transitive requires org.junit.platform.commons transitive requires org.junit.platform.engine transitive uses org.junit.platform.engine.TestEngine uses org.junit.platform.launcher.LauncherDiscoveryListener uses org.junit.platform.launcher.LauncherInterceptor uses org.junit.platform.launcher.LauncherSessionListener uses org.junit.platform.launcher.PostDiscoveryFilter uses org.junit.platform.launcher.TestExecutionListener provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.launcher.listeners.UniqueIdTrackingListener junit-platform-reporting.expected.txt000066400000000000000000000011431455764576500363070ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.reporting@${platformVersion} jar:file:.+/junit-platform-reporting-\d.+\.jar..module-info\.class exports org.junit.platform.reporting.legacy exports org.junit.platform.reporting.legacy.xml exports org.junit.platform.reporting.open.xml requires java.base mandated requires java.xml requires org.apiguardian.api static transitive requires org.junit.platform.commons requires org.junit.platform.engine transitive requires org.junit.platform.launcher transitive provides org.junit.platform.launcher.TestExecutionListener with org.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener junit-platform-runner.expected.txt000066400000000000000000000005771455764576500356210ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.runner@${platformVersion} jar:file:.+/junit-platform-runner-\d.+\.jar..module-info\.class exports org.junit.platform.runner requires java.base mandated requires junit transitive requires org.apiguardian.api static transitive requires org.junit.platform.launcher transitive requires org.junit.platform.suite.api transitive requires org.junit.platform.suite.commons junit-platform-suite-api.expected.txt000066400000000000000000000004221455764576500361750ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.suite.api@${platformVersion} jar:file:.+/junit-platform-suite-api-\d.+\.jar..module-info\.class exports org.junit.platform.suite.api requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.platform.commons transitive junit-platform-suite-commons.expected.txt000066400000000000000000000007231455764576500371030ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.suite.commons@${platformVersion} jar:file:.+/junit-platform-suite-commons-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher transitive requires org.junit.platform.suite.api qualified exports org.junit.platform.suite.commons to org.junit.platform.runner org.junit.platform.suite.engine junit-platform-suite-engine.expected.txt000066400000000000000000000010011455764576500366630ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.suite.engine@${platformVersion} jar:file:.+/junit-platform-suite-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher requires org.junit.platform.suite.api requires org.junit.platform.suite.commons provides org.junit.platform.engine.TestEngine with org.junit.platform.suite.engine.SuiteTestEngine contains org.junit.platform.suite.engine junit-platform-suite.expected.txt000066400000000000000000000003541455764576500354320ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.suite@${platformVersion} jar:file:.+/junit-platform-suite-\d.+\.jar..module-info\.class requires java.base mandated requires org.junit.platform.suite.api transitive requires org.junit.platform.suite.engine transitive junit-platform-testkit.expected.txt000066400000000000000000000007301455764576500357660ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.platform.testkit@${platformVersion} jar:file:.+/junit-platform-testkit-\d.+\.jar..module-info\.class exports org.junit.platform.testkit.engine requires java.base mandated requires org.apiguardian.api static transitive requires org.assertj.core transitive requires org.junit.platform.commons requires org.junit.platform.engine transitive requires org.junit.platform.launcher transitive requires org.opentest4j transitive uses org.junit.platform.engine.TestEngine junit-vintage-engine.expected.txt000066400000000000000000000005341455764576500353570ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/jar-describe-moduleorg.junit.vintage.engine@${vintageVersion} jar:file:.+/junit-vintage-engine-\d.+\.jar..module-info\.class requires java.base mandated requires junit requires org.apiguardian.api static requires org.junit.platform.engine provides org.junit.platform.engine.TestEngine with org.junit.vintage.engine.VintageTestEngine contains org.junit.vintage.engine junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/000077500000000000000000000000001455764576500260165ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/pom.xml000066400000000000000000000042201455764576500273310ustar00rootroot00000000000000 4.0.0 platform.tooling.support.tests java-versions 1.0-SNAPSHOT UTF-8 ${env.JUNIT_JUPITER_VERSION} ${env.JUNIT_PLATFORM_VERSION} org.junit.jupiter junit-jupiter-engine ${junit.jupiter.version} test org.junit.platform junit-platform-commons ${junit.platform.version} test maven-compiler-plugin 3.8.1 1.8 1.8 maven-surefire-plugin 2.22.2 local-temp file://${maven.repo} true true junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/src/000077500000000000000000000000001455764576500266055ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/src/test/000077500000000000000000000000001455764576500275645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/src/test/java/000077500000000000000000000000001455764576500305055ustar00rootroot00000000000000JUnitPlatformCommonsTests.java000066400000000000000000000022421455764576500364060ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/java-versions/src/test/java /* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnJre; import org.junit.jupiter.api.condition.EnabledOnJre; import org.junit.jupiter.api.condition.JRE; import org.junit.platform.commons.util.ModuleUtils; class JUnitPlatformCommonsTests { @Test @EnabledOnJre(JRE.JAVA_8) void onJava8() { assertFalse(ModuleUtils.isJavaPlatformModuleSystemAvailable()); assertFalse(ModuleUtils.getModuleName(Object.class).isPresent()); } @Test @DisabledOnJre(JRE.JAVA_8) void onJava9OrHigher() { assertTrue(ModuleUtils.isJavaPlatformModuleSystemAvailable()); assertEquals("java.base", ModuleUtils.getModuleName(Object.class).orElseThrow(Error::new)); } } junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/000077500000000000000000000000001455764576500260175ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/pom.xml000066400000000000000000000064131455764576500273400ustar00rootroot00000000000000 4.0.0 com.example maven-starter 1.0-SNAPSHOT UTF-8 1.8 ${maven.compiler.source} ${env.JUNIT_JUPITER_VERSION} org.junit.jupiter junit-jupiter test org.junit.platform junit-platform-reporting test org.junit junit-bom ${junit.bom.version} pom import maven-compiler-plugin 3.8.1 maven-surefire-plugin 2.22.2 junit.platform.reporting.open.xml.enabled = true junit.platform.reporting.output.dir = target/surefire-reports org.codehaus.gmaven groovy-maven-plugin 2.1.1 validate execute println("Using Java version: ${java.version}") local-temp file://${maven.repo} true true junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/000077500000000000000000000000001455764576500266065ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/000077500000000000000000000000001455764576500275325ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/java/000077500000000000000000000000001455764576500304535ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/java/com/000077500000000000000000000000001455764576500312315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/java/com/example/000077500000000000000000000000001455764576500326645ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500342535ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/java/com/exampleCalculator.java000066400000000000000000000006521455764576500372120ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/main/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; public class Calculator { public int add(int a, int b) { return a + b; } } junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/000077500000000000000000000000001455764576500275655ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/java/000077500000000000000000000000001455764576500305065ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/java/com/000077500000000000000000000000001455764576500312645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/java/com/example/000077500000000000000000000000001455764576500327175ustar00rootroot00000000000000project/000077500000000000000000000000001455764576500343065ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/java/com/exampleCalculatorTests.java000066400000000000000000000022271455764576500402700ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-starter/src/test/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class CalculatorTests { @Test @DisplayName("1 + 1 = 2") void addsTwoNumbers() { Calculator calculator = new Calculator(); assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2"); } @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({ // "0, 1, 1", // "1, 2, 3", // "49, 51, 100", // "1, 100, 101" // }) void add(int first, int second, int expectedResult) { Calculator calculator = new Calculator(); assertEquals(expectedResult, calculator.add(first, second), () -> first + " + " + second + " should equal " + expectedResult); } } junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/000077500000000000000000000000001455764576500310265ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml000066400000000000000000000053231455764576500323460ustar00rootroot00000000000000 4.0.0 com.example maven-surefire-compatibility 1.0-SNAPSHOT UTF-8 1.8 ${maven.compiler.source} ${env.JUNIT_JUPITER_VERSION} org.junit.jupiter junit-jupiter test org.junit junit-bom ${junit.bom.version} pom import maven-compiler-plugin 3.8.1 maven-surefire-plugin ${surefire.version} junit.platform.listeners.uid.tracking.enabled = true local-temp file://${maven.repo} true true manual-platform-dependency org.junit.platform junit-platform-launcher test junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/000077500000000000000000000000001455764576500316155ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/000077500000000000000000000000001455764576500325745ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/java/000077500000000000000000000000001455764576500335155ustar00rootroot00000000000000com/000077500000000000000000000000001455764576500342145ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/javaexample/000077500000000000000000000000001455764576500356475ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/java/comproject/000077500000000000000000000000001455764576500373155ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/java/com/exampleDummyTests.java000066400000000000000000000011741455764576500423010ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/maven-surefire-compatibility/src/test/java/com/example/project/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.project; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class DummyTests { @Test void test() { } } junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/000077500000000000000000000000001455764576500265515ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/000077500000000000000000000000001455764576500301755ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/pom.xml000066400000000000000000000050351455764576500315150ustar00rootroot00000000000000 4.0.0 platform.tooling.support.tests multi-release-jar 1.0-SNAPSHOT UTF-8 ${env.JUNIT_JUPITER_VERSION} ${env.JUNIT_VINTAGE_VERSION} ${env.JUNIT_PLATFORM_VERSION} org.junit.jupiter junit-jupiter-engine ${junit.jupiter.version} test org.junit.platform junit-platform-reporting ${junit.platform.version} test maven-compiler-plugin 3.8.1 11 de.sormuras.junit junit-platform-maven-plugin 1.1.5 true JAVA true local-temp file://${maven.repo} true true junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/000077500000000000000000000000001455764576500307645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/000077500000000000000000000000001455764576500317435ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/java/000077500000000000000000000000001455764576500326645ustar00rootroot00000000000000integration/000077500000000000000000000000001455764576500351305ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/javaintegration/000077500000000000000000000000001455764576500374535ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/java/integrationJupiterIntegrationTests.java000066400000000000000000000036031455764576500451710ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/java/integration/integration/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package integration; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.MethodOrderer.Alphanumeric; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.discovery.ModuleSelector; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.junit.platform.launcher.core.LauncherFactory; @TestMethodOrder(Alphanumeric.class) class JupiterIntegrationTests { @Test void packageName() { assertEquals("integration", getClass().getPackageName()); } @Test void moduleIsNamed() { assumeTrue(getClass().getModule().isNamed(), "not running on the module-path"); assertEquals("integration", getClass().getModule().getName()); } @Test void resolve() { var selector = DiscoverySelectors.selectClass(getClass()); var testPlan = LauncherFactory.create().discover( request().selectors(selector).filters(includeEngines("junit-jupiter")).build()); var engine = testPlan.getRoots().iterator().next(); assertEquals(1, testPlan.getChildren(engine).size()); // JupiterIntegrationTests.class assertEquals(3, testPlan.getChildren(testPlan.getChildren(engine).iterator().next()).size()); // 3 test methods } } ModuleUtilsTests.java000066400000000000000000000041141455764576500436070ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/multi-release-jar/default/src/test/java/integration/integration/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package integration; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.module.ModuleDescriptor; import java.util.List; import java.util.Set; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ClassFilter; import org.junit.platform.commons.util.ModuleUtils; /** * Unit tests for {@link ModuleUtils}. * * @since 1.1 */ class ModuleUtilsTests { @Test void javaPlatformModuleSystemIsAvailable() { assertTrue(ModuleUtils.isJavaPlatformModuleSystemAvailable()); } @Test void findAllNonSystemBootModuleNames() { Set moduleNames = ModuleUtils.findAllNonSystemBootModuleNames(); assertTrue(moduleNames.isEmpty()); } @Test void findAllClassesInModule() { ClassFilter modular = ClassFilter.of(name -> name.contains("Module"), type -> true); List> classes = ModuleUtils.findAllClassesInModule("java.base", modular); assertFalse(classes.isEmpty()); assertTrue(classes.contains(Module.class)); assertTrue(classes.contains(ModuleDescriptor.class)); } @Test void preconditions() { Class expected = PreconditionViolationException.class; assertThrows(expected, () -> ModuleUtils.getModuleName(null)); assertThrows(expected, () -> ModuleUtils.getModuleVersion(null)); assertThrows(expected, () -> ModuleUtils.findAllClassesInModule(null, null)); assertThrows(expected, () -> ModuleUtils.findAllClassesInModule("", null)); assertThrows(expected, () -> ModuleUtils.findAllClassesInModule(" ", null)); assertThrows(expected, () -> ModuleUtils.findAllClassesInModule("java.base", null)); } } junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/000077500000000000000000000000001455764576500253575ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/expected-err.txt000066400000000000000000000016011455764576500305050ustar00rootroot00000000000000.+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded LauncherInterceptor instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded LauncherSessionListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines .+ Discovered TestEngines: - junit-jupiter .+ - junit-vintage .+ - junit-platform-suite .+ .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded PostDiscoveryFilter instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded LauncherDiscoveryListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded TestExecutionListener instances: .+ .+ org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines .+ Discovered TestEngines: - junit-jupiter .+ - junit-vintage .+ - junit-platform-suite .+ junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/expected-out.txt000066400000000000000000000010131455764576500305210ustar00rootroot00000000000000>> JAVA VERSION + TREE >> Failures (2): >> STACKTRACE >> Test run finished after \d+ ms [ 11 containers found ] [ 0 containers skipped ] [ 11 containers started ] [ 0 containers aborted ] [ 11 containers successful ] [ 0 containers failed ] [ 10 tests found ] [ 2 tests skipped ] [ 8 tests started ] [ 1 tests aborted ] [ 5 tests successful ] [ 2 tests failed ] junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/logging.properties000066400000000000000000000001571455764576500311260ustar00rootroot00000000000000handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=CONFIG org.junit.level=CONFIG junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/000077500000000000000000000000001455764576500261465ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/standalone/000077500000000000000000000000001455764576500302765ustar00rootroot00000000000000JupiterIntegration.java000066400000000000000000000014151455764576500347110ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/standalone/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package standalone; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class JupiterIntegration { @Test void successful() { } @Test @Disabled("integration-test-disabled") void disabled() { } @Test void abort() { Assumptions.assumeTrue(false, "integration-test-abort"); } @Test void fail() { Assertions.fail("integration-test-fail"); } } JupiterParamsIntegration.java000066400000000000000000000013011455764576500360470ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/standalone/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package standalone; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; class JupiterParamsIntegration { @ParameterizedTest(name = "[{index}] argument={0}") @ValueSource(strings = "test") void parameterizedTest(String argument) { assertEquals("test", argument); } } SuiteIntegration.java000066400000000000000000000011711455764576500343570ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/standalone/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package standalone; import org.junit.jupiter.api.Test; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; @Suite @SelectClasses(SuiteIntegration.SingleTestContainer.class) class SuiteIntegration { static class SingleTestContainer { @Test void successful() { } } } VintageIntegration.java000066400000000000000000000015231455764576500346640ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/standalone/src/standalone/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package standalone; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.junit.runners.MethodSorters.NAME_ASCENDING; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; @FixMethodOrder(NAME_ASCENDING) public class VintageIntegration { @Test @Ignore("integr4tion test") public void ignored() { fail("this test should be ignored"); } @Test public void succ3ssful() { assertEquals(3, 1 + 2); } @Test public void f4il() { fail("f4iled"); } } junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/000077500000000000000000000000001455764576500246645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/build.gradle.kts000066400000000000000000000015711455764576500277470ustar00rootroot00000000000000import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent plugins { java } repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() } dependencies { val junit4Version = System.getProperty("junit4Version", "4.12") testImplementation("junit:junit:$junit4Version") val vintageVersion = System.getenv("JUNIT_VINTAGE_VERSION") ?: "5.3.2" testImplementation("org.junit.vintage:junit-vintage-engine:$vintageVersion") { exclude(group = "junit") because("we want to override it to test against different versions") } } tasks.test { useJUnitPlatform() testLogging { events = setOf(TestLogEvent.STARTED, TestLogEvent.PASSED, TestLogEvent.FAILED) afterSuite(KotlinClosure2({ _, result -> result.exception?.printStackTrace(System.out) })) } } junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/pom.xml000066400000000000000000000040711455764576500262030ustar00rootroot00000000000000 4.0.0 com.example vintage 1.0-SNAPSHOT UTF-8 1.8 ${maven.compiler.source} ${env.JUNIT_VINTAGE_VERSION} org.junit.vintage junit-vintage-engine ${vintageVersion} test junit junit junit junit ${junit4Version} test maven-compiler-plugin 3.8.1 maven-surefire-plugin 2.22.2 local-temp file://${maven.repo} true true junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/settings.gradle.kts000066400000000000000000000000351455764576500305020ustar00rootroot00000000000000rootProject.name = "vintage" junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/000077500000000000000000000000001455764576500254535ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/000077500000000000000000000000001455764576500264325ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/java/000077500000000000000000000000001455764576500273535ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/java/com/000077500000000000000000000000001455764576500301315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/java/com/example/000077500000000000000000000000001455764576500315645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/java/com/example/vintage/000077500000000000000000000000001455764576500332215ustar00rootroot00000000000000VintageTest.java000066400000000000000000000010361455764576500362420ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/projects/vintage/src/test/java/com/example/vintage/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package com.example.vintage; import static org.junit.Assert.*; import org.junit.Test; public class VintageTest { @Test public void success() { // pass } @Test public void failure() { fail("expected to fail"); } } junit5-r5.10.2/platform-tooling-support-tests/src/000077500000000000000000000000001455764576500221655ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/000077500000000000000000000000001455764576500231115ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/000077500000000000000000000000001455764576500240325ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/000077500000000000000000000000001455764576500256565ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/000077500000000000000000000000001455764576500273315ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/000077500000000000000000000000001455764576500310455ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java000066400000000000000000000115401455764576500331300ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @since 1.3 */ public class Helper { public static final Duration TOOL_TIMEOUT = Duration.ofMinutes(3); private static final Path ROOT = Paths.get(".."); private static final Path GRADLE_PROPERTIES = ROOT.resolve("gradle.properties"); private static final Path SETTINGS_GRADLE = ROOT.resolve("settings.gradle.kts"); private static final Properties gradleProperties = new Properties(); static { try { gradleProperties.load(Files.newInputStream(GRADLE_PROPERTIES)); } catch (Exception e) { throw new AssertionError("loading gradle.properties failed", e); } } public static String version(String module) { if (module.startsWith("junit-jupiter")) { return gradleProperties.getProperty("version"); } if (module.startsWith("junit-platform")) { return gradleProperties.getProperty("platformVersion"); } if (module.startsWith("junit-vintage")) { return gradleProperties.getProperty("vintageVersion"); } throw new AssertionError("Unknown module: " + module); } static String groupId(String artifactId) { if (artifactId.startsWith("junit-jupiter")) { return "org.junit.jupiter"; } if (artifactId.startsWith("junit-platform")) { return "org.junit.platform"; } if (artifactId.startsWith("junit-vintage")) { return "org.junit.vintage"; } return "org.junit"; } public static String replaceVersionPlaceholders(String line) { line = line.replace("${jupiterVersion}", version("junit-jupiter")); line = line.replace("${vintageVersion}", version("junit-vintage")); line = line.replace("${platformVersion}", version("junit-platform")); return line; } public static List loadModuleDirectoryNames() { var moduleLinePattern = Pattern.compile("include\\(\"(.+)\"\\)"); try (var stream = Files.lines(SETTINGS_GRADLE) // .map(moduleLinePattern::matcher) // .filter(Matcher::matches) // .map(matcher -> matcher.group(1)) // .filter(name -> name.startsWith("junit-")) // .filter(name -> !name.equals("junit-bom")) // .filter(name -> !name.equals("junit-platform-console-standalone"))) { return stream.collect(Collectors.toList()); } catch (Exception e) { throw new AssertionError("loading module directory names failed: " + SETTINGS_GRADLE); } } static JarFile createJarFile(String module) { var path = MavenRepo.jar(module); try { return new JarFile(path.toFile()); } catch (IOException e) { throw new UncheckedIOException("Creating JarFile for '" + path + "' failed.", e); } } public static List loadJarFiles() { return loadModuleDirectoryNames().stream().map(Helper::createJarFile).collect(Collectors.toList()); } public static Optional getJavaHome(String version) { // First, try various system sources... var sources = Stream.of( // System.getProperty("java.home." + version), // System.getProperty("java." + version), // System.getProperty("jdk.home." + version), // System.getProperty("jdk." + version), // System.getenv("JAVA_HOME_" + version), // System.getenv("JAVA_" + version), // System.getenv("JDK" + version) // ); return sources.filter(Objects::nonNull).findFirst().map(Path::of); } /** Load, here copy, modular jar files to the given target directory. */ public static void loadAllJUnitModules(Path target) throws Exception { for (var module : loadModuleDirectoryNames()) { var jar = MavenRepo.jar(module); Files.copy(jar, target.resolve(jar.getFileName())); } } /** Walk directory tree structure. */ public static List treeWalk(Path root) { var lines = new ArrayList(); treeWalk(root, lines::add); return lines; } /** Walk directory tree structure. */ public static void treeWalk(Path root, Consumer out) { try (var stream = Files.walk(root)) { stream.map(root::relativize) // .map(path -> path.toString().replace('\\', '/')) // .sorted().filter(Predicate.not(String::isEmpty)) // .forEach(out); } catch (Exception e) { throw new Error("Walking tree failed: " + root, e); } } } junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/MavenRepo.java000066400000000000000000000034641455764576500336130ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.function.Predicate; import java.util.stream.Stream; public class MavenRepo { private MavenRepo() { } public static Path dir() { var candidates = Stream.of(Path.of("../build/repo")); var candidate = candidates.filter(Files::isDirectory).findFirst().orElse(Path.of("build/repo")); return Path.of(System.getProperty("maven.repo", candidate.toString())); } public static Path jar(String artifactId) { return artifact(artifactId, fileName -> fileName.endsWith(".jar") // && !fileName.endsWith("-sources.jar") // && !fileName.endsWith("-javadoc.jar")); } public static Path gradleModuleMetadata(String artifactId) { return artifact(artifactId, fileName -> fileName.endsWith(".module")); } public static Path pom(String artifactId) { return artifact(artifactId, fileName -> fileName.endsWith(".pom")); } private static Path artifact(String artifactId, Predicate fileNamePredicate) { var parentDir = dir() // .resolve(Helper.groupId(artifactId).replace('.', File.separatorChar)) // .resolve(artifactId) // .resolve(Helper.version(artifactId)); try (var files = Files.list(parentDir)) { return files.filter( file -> fileNamePredicate.test(file.getFileName().toString())).findFirst().orElseThrow(); } catch (IOException e) { throw new UncheckedIOException(e); } } } junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/Request.java000066400000000000000000000116351455764576500333460ustar00rootroot00000000000000/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support; import java.io.FileFilter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Stream; import de.sormuras.bartholdy.Configuration; import de.sormuras.bartholdy.Result; import de.sormuras.bartholdy.Tool; import de.sormuras.bartholdy.tool.Maven; import org.apache.commons.io.FileUtils; /** * @since 1.3 */ public class Request { public static final Path PROJECTS = Paths.get("projects"); private static final Path TOOLS = Paths.get("build", "test-tools"); public static final Path WORKSPACE = Paths.get("build", "test-workspace"); public static Builder builder() { return new Builder(); } public static Maven maven() { return new Maven(Path.of(System.getProperty("mavenDistribution"))); } private Tool tool; private String project; private String workspace; private List arguments = new ArrayList<>(); private Map environment = new HashMap<>(); private FileFilter copyProjectToWorkspaceFileFilter; private Duration timeout = Duration.ofMinutes(1); public String getProject() { return project; } public FileFilter getCopyProjectToWorkspaceFileFilter() { return copyProjectToWorkspaceFileFilter; } public String getWorkspace() { return workspace; } public Map getEnvironment() { return environment; } public List getArguments() { return arguments; } public Duration getTimeout() { return timeout; } public Result run() { return run(true); } public Result run(boolean cleanWorkspace) { try { // sanity check if (!Files.isDirectory(PROJECTS)) { var cwd = Paths.get(".").normalize().toAbsolutePath(); throw new IllegalStateException("Directory " + PROJECTS + " not found in: " + cwd); } Files.createDirectories(TOOLS); Files.createDirectories(WORKSPACE); var workspace = WORKSPACE.resolve(getWorkspace()); if (cleanWorkspace) { FileUtils.deleteQuietly(workspace.toFile()); var project = PROJECTS.resolve(getProject()); if (Files.isDirectory(project)) { var filter = getCopyProjectToWorkspaceFileFilter(); FileUtils.copyDirectory(project.toFile(), workspace.toFile(), filter); } } var configuration = Configuration.builder(); configuration.setArguments(getArguments()); configuration.setWorkingDirectory(workspace); configuration.setTimeout(getTimeout()); configuration.getEnvironment().putAll(getEnvironment()); var result = tool.run(configuration.build()); System.out.println(result.getOutput("out")); System.err.println(result.getOutput("err")); return result; } catch (Exception e) { throw new IllegalStateException("run failed", e); } } public static class Builder { private final Request request = new Request(); public Request build() { if (request.project == null) { throw new IllegalStateException("project must not be null"); } if (request.workspace == null) { request.workspace = request.project; } buildEnvironment(request.environment); request.arguments = List.copyOf(request.arguments); request.environment = Map.copyOf(request.environment); return request; } private void buildEnvironment(Map environment) { environment.computeIfAbsent("JUNIT_JUPITER_VERSION", key -> Helper.version("junit-jupiter")); environment.computeIfAbsent("JUNIT_VINTAGE_VERSION", key -> Helper.version("junit-vintage")); environment.computeIfAbsent("JUNIT_PLATFORM_VERSION", key -> Helper.version("junit-platform")); } public Builder setTool(Tool tool) { request.tool = tool; return this; } public Builder setJavaHome(Path javaHome) { return putEnvironment("JAVA_HOME", javaHome.normalize().toAbsolutePath().toString()); } public Builder setProject(String project) { request.project = project; return this; } public Builder setProjectToWorkspaceCopyFileFilter(FileFilter copyProjectToWorkspaceFileFilter) { request.copyProjectToWorkspaceFileFilter = copyProjectToWorkspaceFileFilter; return this; } public Builder setWorkspace(String workspace) { request.workspace = workspace; return this; } public Builder addArguments(Object... arguments) { Stream.of(arguments).map(Object::toString).forEach(request.arguments::add); return this; } public Builder putEnvironment(String key, String value) { request.environment.put(key, value); return this; } public Builder setTimeout(Duration timeout) { request.timeout = timeout; return this; } } } ThirdPartyJars.java000066400000000000000000000021141455764576500345410ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.Stream; public class ThirdPartyJars { private ThirdPartyJars() { } public static void copy(Path targetDir, String group, String artifact) throws Exception { Path source = Stream.of(System.getProperty("thirdPartyJars").split(File.pathSeparator)) // .filter(it -> it.replace(File.separator, "/").contains("/" + group + "/" + artifact + "/")) // .map(Path::of) // .findFirst() // .orElseThrow(() -> new AssertionError("Failed to find JAR file for " + group + ":" + artifact)); Files.copy(source, targetDir.resolve(source.getFileName()), REPLACE_EXISTING); } } package-info.java000066400000000000000000000001271455764576500341550ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/main/java/platform/tooling/support/** * Tooling support helper. * * @since 1.3 */ package platform.tooling.support; junit5-r5.10.2/platform-tooling-support-tests/src/test/000077500000000000000000000000001455764576500231445ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/000077500000000000000000000000001455764576500240655ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/000077500000000000000000000000001455764576500257115ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/000077500000000000000000000000001455764576500273645ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/000077500000000000000000000000001455764576500311005ustar00rootroot00000000000000HelperTests.java000066400000000000000000000042101455764576500341230ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.nio.file.Files; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; class HelperTests { @Test void loadModuleDirectoryNames() { assertLinesMatch(List.of( // "junit-jupiter", // "junit-jupiter-api", // "junit-jupiter-engine", // "junit-jupiter-migrationsupport", // "junit-jupiter-params", // "junit-platform-commons", // "junit-platform-console", // "junit-platform-engine", // "junit-platform-jfr", // "junit-platform-launcher", // "junit-platform-reporting", // "junit-platform-runner", // "junit-platform-suite", // "junit-platform-suite-api", // "junit-platform-suite-commons", // "junit-platform-suite-engine", // "junit-platform-testkit", // "junit-vintage-engine"// ), Helper.loadModuleDirectoryNames()); } @Test void version() { assertNotNull(Helper.version("junit-jupiter")); assertNotNull(Helper.version("junit-vintage")); assertNotNull(Helper.version("junit-platform")); } @Test void nonExistingJdkVersionYieldsAnEmptyOptional() { assertEquals(Optional.empty(), Helper.getJavaHome("does not exist")); } @ParameterizedTest @ValueSource(ints = 8) void checkJavaHome(int version) { var home = Helper.getJavaHome(String.valueOf(version)); assumeTrue(home.isPresent(), "No 'jdk' element found in Maven toolchain for: " + version); assertTrue(Files.isDirectory(home.get())); } } junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/000077500000000000000000000000001455764576500322425ustar00rootroot00000000000000AntStarterTests.java000066400000000000000000000037451455764576500361510ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static platform.tooling.support.tests.XmlAssertions.verifyContainsExpectedStartedOpenTestReport; import java.util.List; import de.sormuras.bartholdy.tool.Java; import org.apache.tools.ant.Main; import org.junit.jupiter.api.Test; import platform.tooling.support.Request; /** * @since 1.3 */ class AntStarterTests { @Test void ant_starter() { var request = Request.builder() // .setTool(new Java()) // .setProject("ant-starter") // .addArguments("-cp", System.getProperty("antJars"), Main.class.getName()) // .addArguments("-verbose") // .build(); var result = request.run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err"), "error log isn't empty"); assertLinesMatch(List.of(">> HEAD >>", // "test.junit.launcher:", // ">>>>", // "\\[junitlauncher\\] Tests run: 5, Failures: 0, Aborted: 0, Skipped: 0, Time elapsed: .+ sec", // ">>>>", // "test.console.launcher:", // ">>>>", // " \\[java\\] Test run finished after [\\d]+ ms", // ">>>>", // " \\[java\\] \\[ 5 tests successful \\]", // " \\[java\\] \\[ 0 tests failed \\]", // ">> TAIL >>"), // result.getOutputLines("out")); var testResultsDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("build/test-report"); verifyContainsExpectedStartedOpenTestReport(testResultsDir); } } ArchUnitTests.java000066400000000000000000000106531455764576500355730ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static com.tngtech.archunit.base.DescribedPredicate.describe; import static com.tngtech.archunit.base.DescribedPredicate.not; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.ANONYMOUS_CLASSES; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.TOP_LEVEL_CLASSES; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAnyPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleName; import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC; import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining; import static com.tngtech.archunit.lang.conditions.ArchPredicates.are; import static com.tngtech.archunit.lang.conditions.ArchPredicates.have; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.loadJarFiles; import java.util.Set; import java.util.stream.Collectors; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.Location; import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.junit.LocationProvider; import com.tngtech.archunit.lang.ArchRule; import com.tngtech.archunit.library.GeneralCodingRules; import org.apiguardian.api.API; @AnalyzeClasses(locations = ArchUnitTests.AllJars.class) class ArchUnitTests { @ArchTest private final ArchRule allPublicTopLevelTypesHaveApiAnnotations = classes() // .that(have(modifier(PUBLIC))) // .and(TOP_LEVEL_CLASSES) // .and(not(ANONYMOUS_CLASSES)) // .and(not(describe("are Kotlin SAM type implementations", simpleName("")))) // .and(not(describe("are shadowed", resideInAnyPackage("..shadow..")))) // .should().beAnnotatedWith(API.class); @ArchTest void allAreIn(JavaClasses classes) { // about 928 classes found in all jars assertTrue(classes.size() > 800, "expected more than 800 classes, got: " + classes.size()); } @ArchTest void freeOfCycles(JavaClasses classes) { slices().matching("org.junit.(*)..").should().beFreeOfCycles().check(classes); } @ArchTest void avoidJavaUtilLogging(JavaClasses classes) { // LoggerFactory.java:80 -> sets field LoggerFactory$DelegatingLogger.julLogger var subset = classes.that(are(not(name("org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger")))); GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING.check(subset); } @ArchTest void avoidThrowingGenericExceptions(JavaClasses classes) { // LoggerFactory.java:155 -> new Throwable() var subset = classes.that(are(not( name("org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger").or(nameContaining(".shadow."))))); GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS.check(subset); } @ArchTest void avoidAccessingStandardStreams(JavaClasses classes) { // ConsoleLauncher, StreamInterceptor, Picocli et al... var subset = classes // .that(are(not(name("org.junit.platform.console.ConsoleLauncher")))) // .that(are(not(name("org.junit.platform.launcher.core.StreamInterceptor")))) // .that(are(not(name("org.junit.platform.runner.JUnitPlatformRunnerListener")))) // .that(are(not(name("org.junit.platform.testkit.engine.Events")))) // .that(are(not(name("org.junit.platform.testkit.engine.Executions")))) // .that(are(not(resideInAPackage("org.junit.platform.console.shadow.picocli")))); GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS.check(subset); } static class AllJars implements LocationProvider { @Override public Set get(Class testClass) { return loadJarFiles().stream().map(Location::of).collect(Collectors.toSet()); } } } GraalVmStarterTests.java000066400000000000000000000040371455764576500367530ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static platform.tooling.support.tests.XmlAssertions.verifyContainsExpectedStartedOpenTestReport; import java.nio.file.Paths; import java.time.Duration; import de.sormuras.bartholdy.tool.GradleWrapper; import com.gradle.enterprise.testing.annotations.LocalOnly; import org.junit.jupiter.api.Test; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.9.1 */ @LocalOnly(because = "GraalVM is not installed on Test Distribution agents") class GraalVmStarterTests { @Test void runsTestsInNativeImage() { var request = Request.builder() // .setTool(new GradleWrapper(Paths.get(".."))) // .setProject("graalvm-starter") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("javaToolchains", "nativeTest", "--no-daemon", "--stacktrace") // .setTimeout(Duration.ofMinutes(5)) // .build(); var result = request.run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assumeFalse( result.getOutputLines("err").stream().anyMatch(line -> line.contains("No matching toolchains found")), "Abort test if GraalVM is not installed"); assertEquals(0, result.getExitCode()); assertTrue(result.getOutputLines("out").stream().anyMatch(line -> line.contains("BUILD SUCCESSFUL"))); var testResultsDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("build/test-results/test"); verifyContainsExpectedStartedOpenTestReport(testResultsDir); } } GradleKotlinExtensionsTests.java000066400000000000000000000031251455764576500405110ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import de.sormuras.bartholdy.tool.GradleWrapper; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.3 */ class GradleKotlinExtensionsTests { @Test void gradle_wrapper() { var result = Request.builder() // .setTool(new GradleWrapper(Request.PROJECTS.resolve("gradle-kotlin-extensions"))) // .setProject("gradle-kotlin-extensions") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--stacktrace") // .setTimeout(TOOL_TIMEOUT) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode(), "result=" + result); assertTrue(result.getOutputLines("out").stream().anyMatch(line -> line.contains("BUILD SUCCESSFUL"))); } } GradleMissingEngineTests.java000066400000000000000000000037411455764576500377340ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import java.nio.file.Paths; import java.util.List; import de.sormuras.bartholdy.Tool; import de.sormuras.bartholdy.tool.GradleWrapper; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.3 */ class GradleMissingEngineTests { @Test void gradle_wrapper() { test(new GradleWrapper(Paths.get(".."))); } private void test(Tool gradle) { var project = "gradle-missing-engine"; var result = Request.builder() // .setProject(project) // .setWorkspace(project + "-wrapper") // .setTool(gradle) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--debug", "--stacktrace") // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .setTimeout(TOOL_TIMEOUT).build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(1, result.getExitCode()); assertLinesMatch(List.of( // ">> HEAD >>", // ".+DEBUG.+Cannot create Launcher without at least one TestEngine.+", // ">> TAIL >>"), // result.getOutputLines("out")); assertLinesMatch(List.of( // ">> HEAD >>", // ".+ERROR.+FAILURE: Build failed with an exception.", // ">> TAIL >>"), // result.getOutputLines("err")); } } GradleModuleFileTests.java000066400000000000000000000120751455764576500372220ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import java.nio.file.Files; import java.util.List; import org.junit.jupiter.api.Test; import platform.tooling.support.MavenRepo; /** * @since 1.6 */ class GradleModuleFileTests { @Test void jupiterAggregatorGradleModuleMetadataVariants() throws Exception { var expected = List.of(">> HEAD >>", // "{", // " \"formatVersion\": \"1.1\",", // " \"component\": {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter\",", // ">> VERSION >>", // " \"attributes\": {", // ">> STATUS >>", // " }", // " },", // ">> CREATED_BY >>", // " \"variants\": [", // " {", // " \"name\": \"apiElements\",", // " \"attributes\": {", // " \"org.gradle.category\": \"library\",", // " \"org.gradle.dependency.bundling\": \"external\",", // " \"org.gradle.jvm.version\": 8,", // " \"org.gradle.libraryelements\": \"jar\",", // " \"org.gradle.usage\": \"java-api\"", // " },", // " \"dependencies\": [", // " {", // " \"group\": \"org.junit\",", // " \"module\": \"junit-bom\",", // " \"version\": {", // ">> VERSION >>", // " },", // " \"attributes\": {", // " \"org.gradle.category\": \"platform\"", // " },", // " \"endorseStrictVersions\": true", // " },", // " {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter-api\",", // " \"version\": {", // ">> VERSION >>", // " }", // " },", // " {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter-params\",", // " \"version\": {", // ">> VERSION >>", // " }", // " }", // " ],", // " \"files\": [", // " {", // ">> JAR_FILE_DETAILS >>", // " }", // " ]", // " },", // " {", // " \"name\": \"runtimeElements\",", // " \"attributes\": {", // " \"org.gradle.category\": \"library\",", // " \"org.gradle.dependency.bundling\": \"external\",", // " \"org.gradle.jvm.version\": 8,", // " \"org.gradle.libraryelements\": \"jar\",", // " \"org.gradle.usage\": \"java-runtime\"", // " },", // " \"dependencies\": [", // " {", // " \"group\": \"org.junit\",", // " \"module\": \"junit-bom\",", // " \"version\": {", // ">> VERSION >>", // " },", // " \"attributes\": {", // " \"org.gradle.category\": \"platform\"", // " },", // " \"endorseStrictVersions\": true", // " },", // " {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter-api\",", // " \"version\": {", // ">> VERSION >>", // " }", // " },", // " {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter-params\",", // " \"version\": {", // ">> VERSION >>", // " }", // " },", // " {", // " \"group\": \"org.junit.jupiter\",", // " \"module\": \"junit-jupiter-engine\",", // " \"version\": {", // ">> VERSION >>", // " }", // " }", // " ],", // " \"files\": [", // " {", // ">> JAR_FILE_DETAILS >>", // " }", // " ]", // " },", // " {", // " \"name\": \"javadocElements\",", // " \"attributes\": {", // " \"org.gradle.category\": \"documentation\",", // " \"org.gradle.dependency.bundling\": \"external\",", // " \"org.gradle.docstype\": \"javadoc\",", // " \"org.gradle.usage\": \"java-runtime\"", // " },", // " \"files\": [", // " {", // ">> JAR_FILE_DETAILS >>", // " }", // " ]", // " },", // " {", // " \"name\": \"sourcesElements\",", // " \"attributes\": {", // " \"org.gradle.category\": \"documentation\",", // " \"org.gradle.dependency.bundling\": \"external\",", // " \"org.gradle.docstype\": \"sources\",", // " \"org.gradle.usage\": \"java-runtime\"", // " },", // " \"files\": [", // " {", // ">> JAR_FILE_DETAILS >>", // " }", // " ]", // " }", // " ]", // "}"); assertLinesMatch(expected, Files.readAllLines(MavenRepo.gradleModuleMetadata("junit-jupiter"))); } } GradleStarterTests.java000066400000000000000000000037221455764576500366200ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import static platform.tooling.support.tests.XmlAssertions.verifyContainsExpectedStartedOpenTestReport; import java.nio.file.Paths; import de.sormuras.bartholdy.tool.GradleWrapper; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.3 */ class GradleStarterTests { @Test void gradle_wrapper() { var request = Request.builder() // .setTool(new GradleWrapper(Paths.get(".."))) // .setProject("gradle-starter") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--stacktrace") // .setTimeout(TOOL_TIMEOUT) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .build(); var result = request.run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertTrue(result.getOutputLines("out").stream().anyMatch(line -> line.contains("BUILD SUCCESSFUL"))); assertThat(result.getOutput("out")).contains("Using Java version: 1.8"); var testResultsDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("build/test-results/test"); verifyContainsExpectedStartedOpenTestReport(testResultsDir); } } JarContainsManifestFirstTests.java000066400000000000000000000025271455764576500407710ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; import java.io.FileInputStream; import java.nio.file.Files; import java.util.jar.JarInputStream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import platform.tooling.support.MavenRepo; /** * @since 1.8 */ class JarContainsManifestFirstTests { @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") void manifestFirst(String module) throws Exception { var modulePath = MavenRepo.jar(module); if (Files.notExists(modulePath)) { fail("No such file: " + modulePath); } // JarInputStream expects the META-INF/MANIFEST.MF to be at the start of the JAR archive try (final JarInputStream jarInputStream = new JarInputStream(new FileInputStream(modulePath.toFile()))) { assertNotNull(jarInputStream.getManifest(), "MANIFEST.MF should be available via JarInputStream"); } } } JarDescribeModuleTests.java000066400000000000000000000054721455764576500374040ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.lang.module.ModuleFinder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Collectors; import de.sormuras.bartholdy.jdk.Jar; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.3 */ class JarDescribeModuleTests { @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") void describeModule(String module) throws Exception { var modulePath = MavenRepo.jar(module); var result = Request.builder() // .setTool(new Jar()) // .setProject("jar-describe-module") // .setProjectToWorkspaceCopyFileFilter(file -> file.getName().startsWith(module)) // .setWorkspace("jar-describe-module/" + module) // .addArguments("--describe-module", "--file", modulePath) // .build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err"), "error log isn't empty"); var expected = Paths.get("build", "test-workspace", "jar-describe-module", module, module + ".expected.txt"); if (Files.notExists(expected)) { result.getOutputLines("out").forEach(System.err::println); fail("No such file: " + expected); } var expectedLines = Files.lines(expected).map(Helper::replaceVersionPlaceholders).collect(Collectors.toList()); var origin = Path.of("projects", "jar-describe-module", module + ".expected.txt").toUri(); assertLinesMatch(expectedLines, result.getOutputLines("out"), () -> String.format("%s\nError", origin)); } @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") void packageNamesStartWithNameOfTheModule(String module) { var modulePath = MavenRepo.jar(module); var moduleDescriptor = ModuleFinder.of(modulePath).findAll().iterator().next().descriptor(); var moduleName = moduleDescriptor.name(); for (var packageName : moduleDescriptor.packages()) { assertTrue(packageName.startsWith(moduleName)); } } } JavaVersionsTests.java000066400000000000000000000040331455764576500364630ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import java.nio.file.Path; import java.util.List; import de.sormuras.bartholdy.tool.Java; import org.junit.jupiter.api.Test; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.4 */ class JavaVersionsTests { @Test void java_8() { var java8Home = Helper.getJavaHome("8"); assumeTrue(java8Home.isPresent(), "Java 8 installation directory not found!"); var actualLines = execute("8", java8Home.get()); assertTrue(actualLines.contains("[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1")); } @Test void java_default() { var actualLines = execute("default", new Java().getHome()); assertTrue(actualLines.contains("[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1")); } List execute(String version, Path javaHome) { var result = Request.builder() // .setTool(Request.maven()) // .setProject("java-versions") // .setWorkspace("java-versions-" + version) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("--update-snapshots", "--batch-mode", "verify") // .setTimeout(TOOL_TIMEOUT) // .setJavaHome(javaHome) // .build().run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err")); return result.getOutputLines("out"); } } ManifestTests.java000066400000000000000000000064571455764576500356330ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static aQute.bnd.osgi.Constants.VERSION_ATTRIBUTE; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.jar.Attributes; import aQute.bnd.osgi.Domain; import aQute.bnd.osgi.Jar; import aQute.bnd.version.MavenVersion; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.osgi.framework.Version; import org.osgi.framework.VersionRange; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; /** * @since 1.5 */ class ManifestTests { @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") void manifestEntriesAdhereToConventions(String module) throws Exception { var version = Helper.version(module); var jarFile = MavenRepo.jar(module).toFile(); try (var jar = new Jar(jarFile)) { var manifest = jar.getManifest(); var attributes = manifest.getMainAttributes(); assertValue(attributes, "Built-By", "JUnit Team"); assertValue(attributes, "Specification-Title", module); assertValue(attributes, "Specification-Version", specificationVersion(version)); assertValue(attributes, "Specification-Vendor", "junit.org"); assertValue(attributes, "Implementation-Title", module); assertValue(attributes, "Implementation-Version", version); assertValue(attributes, "Implementation-Vendor", "junit.org"); assertValue(attributes, "Automatic-Module-Name", null); assertValue(attributes, "Bundle-ManifestVersion", "2"); assertValue(attributes, "Bundle-SymbolicName", module); assertValue(attributes, "Bundle-Version", MavenVersion.parseMavenString(version).getOSGiVersion().toString()); switch (module) { case "junit-platform-commons" -> assertValue(attributes, "Multi-Release", "true"); case "junit-platform-console" -> assertValue(attributes, "Main-Class", "org.junit.platform.console.ConsoleLauncher"); } var domain = Domain.domain(manifest); domain.getExportPackage().forEach((pkg, attrs) -> { final var stringVersion = attrs.get(VERSION_ATTRIBUTE); assertNotNull(stringVersion); assertDoesNotThrow(() -> new Version(stringVersion)); }); domain.getImportPackage().forEach((pkg, attrs) -> { final var stringVersionRange = attrs.get(VERSION_ATTRIBUTE); if (stringVersionRange == null) { return; } assertDoesNotThrow(() -> new VersionRange(stringVersionRange)); }); } } private static String specificationVersion(String version) { var dash = version.indexOf('-'); if (dash < 0) { return version; } return version.substring(0, dash); } private static void assertValue(Attributes attributes, String name, String expected) { var actual = attributes.getValue(name); assertEquals(expected, actual, String.format("Manifest attribute %s expected to be %s, but is: %s", name, expected, actual)); } } MavenPomFileTests.java000066400000000000000000000042451455764576500364000ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import java.nio.file.Files; import java.util.List; import org.junit.jupiter.api.Test; import platform.tooling.support.MavenRepo; /** * @since 1.4 */ class MavenPomFileTests { @Test void jupiterAggregatorPomDependencies() throws Exception { var expected = List.of(">> HEAD >>", // " ", // " ", // " ", // " org.junit", // " junit-bom", // ">> VERSION >>", // " pom", // " import", // " ", // " ", // " ", // " ", // " ", // " org.junit.jupiter", // " junit-jupiter-api", // ">> VERSION >>", // " compile", // " ", // " ", // " org.junit.jupiter", // " junit-jupiter-params", // ">> VERSION >>", // " compile", // " ", // " ", // " org.junit.jupiter", // " junit-jupiter-engine", // ">> VERSION >>", // " runtime", // " ", // " ", // ">> TAIL >>"); assertLinesMatch(expected, Files.readAllLines(MavenRepo.pom("junit-jupiter"))); } @Test void jupiterAggregatorGradleMetadataMarker() throws Exception { var expected = List.of(">> HEAD >>", // " ", // ">> TAIL >>"); assertLinesMatch(expected, Files.readAllLines(MavenRepo.pom("junit-jupiter"))); } } MavenStarterTests.java000066400000000000000000000040021455764576500364600ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import static platform.tooling.support.tests.XmlAssertions.verifyContainsExpectedStartedOpenTestReport; import org.junit.jupiter.api.Test; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.3 */ class MavenStarterTests { @Test void verifyMavenStarterProject() { var request = Request.builder() // .setTool(Request.maven()) // .setProject("maven-starter") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("--update-snapshots", "--batch-mode", "verify") // .setTimeout(TOOL_TIMEOUT) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .build(); var result = request.run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err")); assertTrue(result.getOutputLines("out").contains("[INFO] BUILD SUCCESS")); assertTrue(result.getOutputLines("out").contains("[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0")); assertThat(result.getOutput("out")).contains("Using Java version: 1.8"); var testResultsDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("target/surefire-reports"); verifyContainsExpectedStartedOpenTestReport(testResultsDir); } } MavenSurefireCompatibilityTests.java000066400000000000000000000047471455764576500413720ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import java.io.IOException; import java.nio.file.Files; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.9.2 */ class MavenSurefireCompatibilityTests { @ParameterizedTest @CsvSource(delimiter = '|', nullValues = "", textBlock = """ 2.22.2 | --activate-profiles=manual-platform-dependency 3.0.0-M4 | """) void testMavenSurefireCompatibilityProject(String surefireVersion, String extraArg) throws IOException { var extraArgs = extraArg == null ? new Object[0] : new Object[] { extraArg }; var request = Request.builder() // .setTool(Request.maven()) // .setProject("maven-surefire-compatibility") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Dsurefire.version=" + surefireVersion) // .addArguments("--update-snapshots", "--batch-mode", "test") // .addArguments(extraArgs) // .setTimeout(TOOL_TIMEOUT) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .build(); var result = request.run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err")); var output = result.getOutputLines("out"); assertTrue(output.contains("[INFO] BUILD SUCCESS")); assertTrue(output.contains("[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0")); var targetDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("target"); try (var stream = Files.list(targetDir)) { assertThat(stream.filter(file -> file.getFileName().toString().startsWith("junit-platform-unique-ids"))) // .hasSize(1); } } } ModularUserGuideTests.java000066400000000000000000000155561455764576500373050ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.spi.ToolProvider; import org.codehaus.groovy.runtime.ProcessGroovyMethods; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import platform.tooling.support.Helper; import platform.tooling.support.ThirdPartyJars; /** * @since 1.5 */ class ModularUserGuideTests { private static final String DOCUMENTATION_MODULE_DESCRIPTOR = """ open module documentation { exports example.testkit; // just here to ensure documentation example sources are compiled requires org.junit.jupiter.api; requires org.junit.jupiter.migrationsupport; requires org.junit.jupiter.params; requires org.junit.platform.engine; requires org.junit.platform.reporting; requires org.junit.platform.runner; requires org.junit.platform.testkit; // Byte Buddy is used by AssertJ's soft assertions which are used by the Engine Test Kit requires net.bytebuddy; requires java.desktop; requires java.logging; requires java.scripting; requires jdk.httpserver; provides org.junit.platform.launcher.LauncherSessionListener with example.session.GlobalSetupTeardownListener; } """; private static List compile(Path temp, Writer out, Writer err) throws Exception { var documentation = Files.createDirectories(temp.resolve("src/documentation")); Files.writeString(documentation.resolve("module-info.java"), DOCUMENTATION_MODULE_DESCRIPTOR); var args = new ArrayList(); args.add("-Xlint"); // enable all default warnings args.add("-proc:none"); // disable annotation processing args.add("-cp"); args.add(""); // set empty class path, otherwise system property "java.class.path" is read args.add("-d"); args.add(temp.resolve("destination").toString()); var lib = Files.createDirectories(temp.resolve("lib")); ThirdPartyJars.copy(lib, "junit", "junit"); ThirdPartyJars.copy(lib, "org.assertj", "assertj-core"); // Byte Buddy is used by AssertJ's soft assertions which are used by the Engine Test Kit ThirdPartyJars.copy(lib, "net.bytebuddy", "byte-buddy"); ThirdPartyJars.copy(lib, "org.apiguardian", "apiguardian-api"); ThirdPartyJars.copy(lib, "org.hamcrest", "hamcrest"); ThirdPartyJars.copy(lib, "org.opentest4j", "opentest4j"); ThirdPartyJars.copy(lib, "com.google.jimfs", "jimfs"); ThirdPartyJars.copy(lib, "com.google.guava", "guava"); Helper.loadAllJUnitModules(lib); args.add("--module-path"); args.add(lib.toString()); args.add("--patch-module"); args.add("documentation=" + Path.of("../documentation/src/main/java") + File.pathSeparator + Path.of("../documentation/src/test/java")); args.add("--module-source-path"); args.add(temp.resolve("src").toString()); args.add(documentation.resolve("module-info.java").toString()); try (var walk = Files.walk(Path.of("../documentation/src/test/java"))) { walk.map(Path::toString) // .filter(s -> s.endsWith(".java")) // // TypeError: systemProperty.get is not a function ?!?! .filter(s -> !s.endsWith("ConditionalTestExecutionDemo.java")) // // Don't include command-line tools that "require io.github.classgraph" .filter(s -> !s.contains("tools")).forEach(args::add); } var javac = ToolProvider.findFirst("javac").orElseThrow(); var code = javac.run(new PrintWriter(out), new PrintWriter(err), args.toArray(String[]::new)); assertEquals(0, code, err.toString()); assertTrue(out.toString().isBlank(), out.toString()); return args; } private static void junit(Path temp, Writer out, Writer err) throws Exception { var command = new ArrayList(); var projectDir = Path.of("../documentation"); command.add(Path.of(System.getProperty("java.home"), "bin", "java").toString()); command.add("-XX:StartFlightRecording:filename=" + temp.resolve("user-guide.jfr")); command.add("--show-version"); command.add("--show-module-resolution"); command.add("--module-path"); command.add(String.join(File.pathSeparator, // temp.resolve("destination").toString(), // temp.resolve("lib").toString() // )); command.add("--add-modules"); command.add("documentation"); // TODO This `patch-module` should work! Why doesn't it? // command.add("--patch-module"); // command.add("documentation=../documentation/src/test/resources/"); Files.copy(projectDir.resolve("src/test/resources/two-column.csv"), temp.resolve("destination/documentation/two-column.csv")); command.add("--module"); command.add("org.junit.platform.console"); command.add("--scan-modules"); command.add("--config"); command.add("enableHttpServer=true"); command.add("--fail-if-no-tests"); command.add("--include-classname"); command.add(".*Tests"); command.add("--include-classname"); command.add(".*Demo"); command.add("--exclude-tag"); command.add("exclude"); // System.out.println("______________"); // command.forEach(System.out::println); var builder = new ProcessBuilder(command).directory(projectDir.toFile()); var java = builder.start(); ProcessGroovyMethods.waitForProcessOutput(java, out, err); var code = java.exitValue(); if (code != 0) { System.out.println(out); System.err.println(err); fail("Unexpected exit code: " + code); } } @Test void runTestsFromUserGuideWithinModularBoundaries(@TempDir Path temp) throws Exception { var out = new StringWriter(); var err = new StringWriter(); var args = compile(temp, out, err); // args.forEach(System.out::println); assertTrue(err.toString().isBlank(), () -> err + "\n\n" + String.join("\n", args)); var listing = Helper.treeWalk(temp); assertLinesMatch(List.of( // "destination", // ">> CLASSES >>", // "lib", // "lib/apiguardian-api-.+\\.jar", // "lib/assertj-core-.+\\.jar", // "lib/byte-buddy-.+", // "lib/guava-.+\\.jar", // "lib/hamcrest-.+\\.jar", // "lib/jimfs-.+\\.jar", // "lib/junit-.+\\.jar", // ">> ALL JUNIT 5 JARS >>", // "lib/opentest4j-.+\\.jar", // "src", // "src/documentation", // "src/documentation/module-info.java" // ), listing); // System.out.println("______________"); // listing.forEach(System.out::println); junit(temp, out, err); } } MultiReleaseJarTests.java000066400000000000000000000062051455764576500371040ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import de.sormuras.bartholdy.Result; import org.junit.jupiter.api.Test; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.4 */ class MultiReleaseJarTests { @Test void checkDefault() throws Exception { var variant = "default"; var expectedLines = List.of( // ">> BANNER >>", // ".", // "'-- JUnit Jupiter [OK]", // " +-- ModuleUtilsTests [OK]", // " | +-- javaPlatformModuleSystemIsAvailable() [OK]", // " | +-- findAllClassesInModule() [OK]", // " | +-- findAllNonSystemBootModuleNames() [OK]", // " | '-- preconditions() [OK]", // " '-- JupiterIntegrationTests [OK]", // " +-- moduleIsNamed() [A] Assumption failed: not running on the module-path", // " +-- packageName() [OK]", // " '-- resolve() [OK]", // "", // "Test run finished after \\d+ ms", // "[ 3 containers found ]", // "[ 0 containers skipped ]", // "[ 3 containers started ]", // "[ 0 containers aborted ]", // "[ 3 containers successful ]", // "[ 0 containers failed ]", // "[ 7 tests found ]", // "[ 0 tests skipped ]", // "[ 7 tests started ]", // "[ 1 tests aborted ]", // "[ 6 tests successful ]", // "[ 0 tests failed ]", // "" // ); var result = mvn(variant); result.getOutputLines("out").forEach(System.out::println); result.getOutputLines("err").forEach(System.err::println); assertEquals(0, result.getExitCode()); assertEquals("", result.getOutput("err")); assertTrue(result.getOutputLines("out").contains("[INFO] BUILD SUCCESS")); var workspace = Path.of("build/test-workspace/multi-release-jar", variant); var actualLines = Files.readAllLines(workspace.resolve("target/junit-platform/console-launcher.out.log")); assertLinesMatch(expectedLines, actualLines); } private Result mvn(String variant) { var result = Request.builder() // .setTool(Request.maven()) // .setProject("multi-release-jar") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("--update-snapshots", "--show-version", "--errors", "--batch-mode", "--file", variant, "test") // .setTimeout(TOOL_TIMEOUT) // .build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); return result; } } PackageCyclesDetectionTests.java000066400000000000000000000027101455764576500404060ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import de.sormuras.bartholdy.Configuration; import de.sormuras.bartholdy.tool.CyclesDetector; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import platform.tooling.support.MavenRepo; /** * @since 1.3 */ class PackageCyclesDetectionTests { @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") @Disabled("Need to pass --module-path...") void moduleDoesNotContainCyclicPackageReferences(String module) { var jar = MavenRepo.jar(module); var result = new CyclesDetector(jar, this::ignore).run(Configuration.of()); assertEquals(0, result.getExitCode(), "result=" + result); } private boolean ignore(String source, String target) { if (source.equals(target)) { return true; } if (source.startsWith("org.junit.jupiter.params.shadow.com.univocity.parsers.")) { return true; } //noinspection RedundantIfStatement if (!target.startsWith("org.junit.")) { return true; } return false; } } StandaloneTests.java000066400000000000000000000524001455764576500361420ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import de.sormuras.bartholdy.Result; import de.sormuras.bartholdy.jdk.Jar; import de.sormuras.bartholdy.jdk.Javac; import de.sormuras.bartholdy.tool.Java; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; /** * @since 1.4 */ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class StandaloneTests { @Test void jarFileWithoutCompiledModuleDescriptorClass() throws Exception { var jar = MavenRepo.jar("junit-platform-console-standalone"); var name = "module-info.class"; var found = new ArrayList(); try (var fileSystem = FileSystems.newFileSystem(jar)) { for (var rootDirectory : fileSystem.getRootDirectories()) { try (var stream = Files.walk(rootDirectory)) { stream.filter(path -> path.getNameCount() > 0) // skip root entry .filter(path -> path.getFileName().toString().equals(name)).forEach(found::add); } } } assertTrue(found.isEmpty(), jar + " must not contain any " + name + " files: " + found); } @Test void listAllObservableEngines() { var result = Request.builder() // .setTool(new Java()) // .setProject("standalone") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("engines", "--disable-ansi-colors", "--disable-banner").build() // .run(false); assertEquals(0, result.getExitCode(), () -> getExitCodeMessage(result)); var jupiterVersion = Helper.version("junit-jupiter-engine"); var suiteVersion = Helper.version("junit-platform-suite-engine"); var vintageVersion = Helper.version("junit-vintage-engine"); assertLinesMatch(""" junit-jupiter (org.junit.jupiter:junit-jupiter-engine:%s) junit-platform-suite (org.junit.platform:junit-platform-suite-engine:%s) junit-vintage (org.junit.vintage:junit-vintage-engine:%s) """.formatted(jupiterVersion, suiteVersion, vintageVersion).lines(), // result.getOutput("out").lines()); } @Test @Order(1) void compile() throws Exception { var workspace = Request.WORKSPACE.resolve("standalone"); var result = Request.builder() // .setTool(new Javac()) // .setProject("standalone") // .addArguments("-Xlint:-options") // .addArguments("--release", "8") // .addArguments("-proc:none") // .addArguments("-d", workspace.resolve("bin")) // .addArguments("--class-path", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments(workspace.resolve("src/standalone/JupiterIntegration.java")) // .addArguments(workspace.resolve("src/standalone/JupiterParamsIntegration.java")) // .addArguments(workspace.resolve("src/standalone/SuiteIntegration.java")) // .addArguments(workspace.resolve("src/standalone/VintageIntegration.java")).build() // .run(); assertEquals(0, result.getExitCode(), () -> getExitCodeMessage(result)); assertTrue(result.getOutput("out").isEmpty()); assertTrue(result.getOutput("err").isEmpty()); // create "tests.jar" that'll be picked-up by "testWithJarredTestClasses()" later var jarFolder = Files.createDirectories(workspace.resolve("jar")); var jarResult = Request.builder() // .setTool(new Jar()) // .setProject("standalone") // .addArguments("--create") // .addArguments("--file", jarFolder.resolve("tests.jar")) // .addArguments("-C", workspace.resolve("bin"), ".") // .build().run(false); assertEquals(0, jarResult.getExitCode(), String.join("\n", jarResult.getOutputLines("out"))); } @Test @Order(2) void discoverTree() { Result result = discover("--details-theme=ascii"); var expected = """ . +-- JUnit Jupiter | +-- JupiterIntegration | | +-- successful() | | +-- fail() | | +-- abort() | | '-- disabled() | +-- SuiteIntegration$SingleTestContainer | | '-- successful() | '-- JupiterParamsIntegration | '-- parameterizedTest(String) +-- JUnit Vintage | '-- VintageIntegration | +-- f4il | +-- ignored | '-- succ3ssful '-- JUnit Platform Suite '-- SuiteIntegration '-- JUnit Jupiter '-- SuiteIntegration$SingleTestContainer '-- successful() [ 11 containers found ] [ 9 tests found ] """.stripIndent(); assertLinesMatch(expected.lines(), result.getOutputLines("out").stream()); } @Test @Order(2) void discoverFlat() { Result result = discover("--details=flat"); var expected = """ JUnit Jupiter ([engine:junit-jupiter]) JupiterIntegration ([engine:junit-jupiter]/[class:standalone.JupiterIntegration]) successful() ([engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:successful()]) fail() ([engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:fail()]) abort() ([engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:abort()]) disabled() ([engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:disabled()]) SuiteIntegration$SingleTestContainer ([engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]) successful() ([engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]/[method:successful()]) JupiterParamsIntegration ([engine:junit-jupiter]/[class:standalone.JupiterParamsIntegration]) parameterizedTest(String) ([engine:junit-jupiter]/[class:standalone.JupiterParamsIntegration]/[test-template:parameterizedTest(java.lang.String)]) JUnit Vintage ([engine:junit-vintage]) VintageIntegration ([engine:junit-vintage]/[runner:standalone.VintageIntegration]) f4il ([engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:f4il(standalone.VintageIntegration)]) ignored ([engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:ignored(standalone.VintageIntegration)]) succ3ssful ([engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:succ3ssful(standalone.VintageIntegration)]) JUnit Platform Suite ([engine:junit-platform-suite]) SuiteIntegration ([engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]) JUnit Jupiter ([engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]/[engine:junit-jupiter]) SuiteIntegration$SingleTestContainer ([engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]/[engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]) successful() ([engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]/[engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]/[method:successful()]) [ 11 containers found ] [ 9 tests found ] """.stripIndent(); assertLinesMatch(expected.lines(), result.getOutputLines("out").stream()); } @Test @Order(2) void discoverVerbose() { Result result = discover("--details=verbose", "--details-theme=ascii"); var expected = """ +-- JUnit Jupiter | +-- JupiterIntegration | | +-- successful() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:successful()] | | | parent: [engine:junit-jupiter]/[class:standalone.JupiterIntegration] | | | source: MethodSource [className = 'standalone.JupiterIntegration', methodName = 'successful', methodParameterTypes = ''] | | +-- fail() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:fail()] | | | parent: [engine:junit-jupiter]/[class:standalone.JupiterIntegration] | | | source: MethodSource [className = 'standalone.JupiterIntegration', methodName = 'fail', methodParameterTypes = ''] | | +-- abort() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:abort()] | | | parent: [engine:junit-jupiter]/[class:standalone.JupiterIntegration] | | | source: MethodSource [className = 'standalone.JupiterIntegration', methodName = 'abort', methodParameterTypes = ''] | | +-- disabled() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.JupiterIntegration]/[method:disabled()] | | | parent: [engine:junit-jupiter]/[class:standalone.JupiterIntegration] | | | source: MethodSource [className = 'standalone.JupiterIntegration', methodName = 'disabled', methodParameterTypes = ''] | '-- JupiterIntegration | +-- SuiteIntegration$SingleTestContainer | | +-- successful() | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]/[method:successful()] | | | parent: [engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer] | | | source: MethodSource [className = 'standalone.SuiteIntegration$SingleTestContainer', methodName = 'successful', methodParameterTypes = ''] | '-- SuiteIntegration$SingleTestContainer | +-- JupiterParamsIntegration | | +-- parameterizedTest(String) | | | tags: [] | | | uniqueId: [engine:junit-jupiter]/[class:standalone.JupiterParamsIntegration]/[test-template:parameterizedTest(java.lang.String)] | | | parent: [engine:junit-jupiter]/[class:standalone.JupiterParamsIntegration] | | | source: MethodSource [className = 'standalone.JupiterParamsIntegration', methodName = 'parameterizedTest', methodParameterTypes = 'java.lang.String'] | '-- JupiterParamsIntegration '-- JUnit Jupiter +-- JUnit Vintage | +-- VintageIntegration | | +-- f4il | | | tags: [] | | | uniqueId: [engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:f4il(standalone.VintageIntegration)] | | | parent: [engine:junit-vintage]/[runner:standalone.VintageIntegration] | | | source: MethodSource [className = 'standalone.VintageIntegration', methodName = 'f4il', methodParameterTypes = ''] | | +-- ignored | | | tags: [] | | | uniqueId: [engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:ignored(standalone.VintageIntegration)] | | | parent: [engine:junit-vintage]/[runner:standalone.VintageIntegration] | | | source: MethodSource [className = 'standalone.VintageIntegration', methodName = 'ignored', methodParameterTypes = ''] | | +-- succ3ssful | | | tags: [] | | | uniqueId: [engine:junit-vintage]/[runner:standalone.VintageIntegration]/[test:succ3ssful(standalone.VintageIntegration)] | | | parent: [engine:junit-vintage]/[runner:standalone.VintageIntegration] | | | source: MethodSource [className = 'standalone.VintageIntegration', methodName = 'succ3ssful', methodParameterTypes = ''] | '-- VintageIntegration '-- JUnit Vintage +-- JUnit Platform Suite | +-- SuiteIntegration | | +-- JUnit Jupiter | | | +-- SuiteIntegration$SingleTestContainer | | | | +-- successful() | | | | | tags: [] | | | | | uniqueId: [engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]/[engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer]/[method:successful()] | | | | | parent: [engine:junit-platform-suite]/[suite:standalone.SuiteIntegration]/[engine:junit-jupiter]/[class:standalone.SuiteIntegration$SingleTestContainer] | | | | | source: MethodSource [className = 'standalone.SuiteIntegration$SingleTestContainer', methodName = 'successful', methodParameterTypes = ''] | | | '-- SuiteIntegration$SingleTestContainer | | '-- JUnit Jupiter | '-- SuiteIntegration '-- JUnit Platform Suite [ 11 containers found ] [ 9 tests found ] """.stripIndent(); assertLinesMatch(expected.lines(), result.getOutputLines("out").stream()); } @Test @Order(2) void discoverNone() { Result result = discover("--details=none"); assertThat(result.getOutputLines("out")).isEmpty(); } @Test @Order(2) void discoverSummary() { Result result = discover("--details=summary"); var expected = """ [ 11 containers found ] [ 9 tests found ] """.stripIndent(); assertLinesMatch(expected.lines(), result.getOutputLines("out").stream()); } @Test @Order(2) void discoverTestFeed() { Result result = discover("--details=testfeed"); var expected = """ JUnit Jupiter > JupiterIntegration > successful() JUnit Jupiter > JupiterIntegration > fail() JUnit Jupiter > JupiterIntegration > abort() JUnit Jupiter > JupiterIntegration > disabled() JUnit Jupiter > SuiteIntegration$SingleTestContainer > successful() JUnit Vintage > VintageIntegration > f4il JUnit Vintage > VintageIntegration > ignored JUnit Vintage > VintageIntegration > succ3ssful JUnit Platform Suite > SuiteIntegration > JUnit Jupiter > SuiteIntegration$SingleTestContainer > successful() [ 11 containers found ] [ 9 tests found ] """.stripIndent(); assertLinesMatch(expected.lines(), result.getOutputLines("out").stream()); } private static Result discover(String... args) { var result = Request.builder() // .setTool(new Java()) // .setProject("standalone") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("discover") // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // .addArguments("--disable-ansi-colors") // .addArguments("--include-classname", "standalone.*") // .addArguments("--classpath", "bin") // .addArguments((Object[]) args) // .build() // .run(false); assertEquals(0, result.getExitCode(), () -> getExitCodeMessage(result)); return result; } @Test @Order(3) void execute() throws IOException { var result = Request.builder() // .setTool(new Java()) // .setProject("standalone") // .addArguments("--show-version") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("execute") // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // .addArguments("--include-classname", "standalone.*") // .addArguments("--classpath", "bin").build() // .run(false); assertEquals(1, result.getExitCode(), () -> getExitCodeMessage(result)); var workspace = Request.WORKSPACE.resolve("standalone"); var expectedOutLines = Files.readAllLines(workspace.resolve("expected-out.txt")); var expectedErrLines = Files.readAllLines(workspace.resolve("expected-err.txt")); assertLinesMatch(expectedOutLines, result.getOutputLines("out")); assertLinesMatch(expectedErrLines, result.getOutputLines("err")); var jupiterVersion = Helper.version("junit-jupiter-engine"); var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.getOutput("err").contains("junit-jupiter" + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); assertTrue(result.getOutput("err").contains("junit-vintage" + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); } @Test @Order(4) void executeOnJava8() throws IOException { Java java8 = getJava8(); var result = Request.builder() // .setTool(java8) // .setJavaHome(java8.getHome()) // .setProject("standalone") // .addArguments("-showversion") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("execute") // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // .addArguments("--include-classname", "standalone.*") // .addArguments("--classpath", "bin").build() // .run(false); assertEquals(1, result.getExitCode(), () -> getExitCodeMessage(result)); var workspace = Request.WORKSPACE.resolve("standalone"); var expectedOutLines = Files.readAllLines(workspace.resolve("expected-out.txt")); var expectedErrLines = getExpectedErrLinesOnJava8(workspace); assertLinesMatch(expectedOutLines, result.getOutputLines("out")); assertLinesMatch(expectedErrLines, result.getOutputLines("err")); var jupiterVersion = Helper.version("junit-jupiter-engine"); var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.getOutput("err").contains("junit-jupiter" + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); assertTrue(result.getOutput("err").contains("junit-vintage" + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); } @Test @Order(5) // https://github.com/junit-team/junit5/issues/2600 void executeOnJava8SelectPackage() throws IOException { Java java8 = getJava8(); var result = Request.builder() // .setTool(java8) // .setJavaHome(java8.getHome()) // .setProject("standalone") // .addArguments("-showversion") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("execute") // .addArguments("--select-package", "standalone") // .addArguments("--disable-banner") // .addArguments("--include-classname", "standalone.*") // .addArguments("--classpath", "bin").build() // .run(false); assertEquals(1, result.getExitCode(), () -> getExitCodeMessage(result)); var workspace = Request.WORKSPACE.resolve("standalone"); var expectedOutLines = Files.readAllLines(workspace.resolve("expected-out.txt")); var expectedErrLines = getExpectedErrLinesOnJava8(workspace); assertLinesMatch(expectedOutLines, result.getOutputLines("out")); assertLinesMatch(expectedErrLines, result.getOutputLines("err")); var jupiterVersion = Helper.version("junit-jupiter-engine"); var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.getOutput("err").contains("junit-jupiter" + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); assertTrue(result.getOutput("err").contains("junit-vintage" + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); } private static List getExpectedErrLinesOnJava8(Path workspace) throws IOException { var expectedErrLines = new ArrayList(); expectedErrLines.add(">> JAVA VERSION >>"); expectedErrLines.addAll(Files.readAllLines(workspace.resolve("expected-err.txt"))); return expectedErrLines; } @Test @Order(6) @Disabled("https://github.com/junit-team/junit5/issues/1724") void executeWithJarredTestClasses() { var jar = MavenRepo.jar("junit-platform-console-standalone"); var path = new ArrayList(); // path.add("bin"); // "exploded" test classes are found, see also test() above path.add(Request.WORKSPACE.resolve("standalone/jar/tests.jar").toAbsolutePath().toString()); path.add(jar.toString()); var result = Request.builder() // .setTool(new Java()) // .setProject("standalone") // .addArguments("--show-version") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // .addArguments("--class-path", String.join(File.pathSeparator, path)) // .addArguments("org.junit.platform.console.ConsoleLauncher") // .addArguments("execute") // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // .addArguments("--include-classname", "standalone.*") // .addArguments("--fail-if-no-tests") // .build() // .run(false); assertEquals(1, result.getExitCode(), () -> getExitCodeMessage(result)); } private static String getExitCodeMessage(Result result) { return "Exit codes don't match. Stdout:\n" + result.getOutput("out") + // "\n\nStderr:\n" + result.getOutput("err") + "\n"; } /** * Special override of class {@link Java} to resolve against a different {@code JAVA_HOME}. */ private static Java getJava8() { Path java8Home = Helper.getJavaHome("8").orElseThrow(TestAbortedException::new); return new Java() { @Override public Path getHome() { return java8Home; } @Override public String getVersion() { return "8"; } }; } } ToolProviderTests.java000066400000000000000000000112671455764576500365100ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; import java.util.Set; import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; import platform.tooling.support.ThirdPartyJars; /** * @since 1.6 */ class ToolProviderTests { private static final Path LIB = Request.WORKSPACE.resolve("tool-provider-tests/lib"); @BeforeAll static void prepareLocalLibraryDirectoryWithJUnitPlatformModules() { try { var lib = Files.createDirectories(LIB); try (var directoryStream = Files.newDirectoryStream(lib, "*.jar")) { for (Path jarFile : directoryStream) { Files.delete(jarFile); } } for (var module : Helper.loadModuleDirectoryNames()) { if (module.startsWith("junit-platform")) { var jar = MavenRepo.jar(module); Files.copy(jar, lib.resolve(module + ".jar")); } } ThirdPartyJars.copy(lib, "org.apiguardian", "apiguardian-api"); ThirdPartyJars.copy(lib, "org.opentest4j", "opentest4j"); } catch (Exception e) { throw new AssertionError("Preparing local library folder failed", e); } } @Test void findAndRunJUnitOnTheClassPath() { try (var loader = new URLClassLoader("junit", urls(LIB), ClassLoader.getPlatformClassLoader())) { var sl = ServiceLoader.load(ToolProvider.class, loader); var junit = StreamSupport.stream(sl.spliterator(), false).filter(p -> p.name().equals("junit")).findFirst(); assertTrue(junit.isPresent(), "Tool 'junit' not found in: " + LIB); assertJUnitPrintsHelpMessage(junit.get()); } catch (IOException e) { throw new AssertionError("Closing URLClassLoader failed: " + e, e); } } @Test void findAndRunJUnitOnTheModulePath() { var finder = ModuleFinder.of(LIB); var modules = finder.findAll().stream() // .map(ModuleReference::descriptor) // .map(ModuleDescriptor::toNameAndVersion) // .sorted() // .collect(Collectors.toList()); // modules.forEach(System.out::println); var bootLayer = ModuleLayer.boot(); var configuration = bootLayer.configuration().resolveAndBind(finder, ModuleFinder.of(), Set.of()); var layer = bootLayer.defineModulesWithOneLoader(configuration, ClassLoader.getPlatformClassLoader()); var sl = ServiceLoader.load(layer, ToolProvider.class); var junit = StreamSupport.stream(sl.spliterator(), false).filter(p -> p.name().equals("junit")).findFirst(); assertTrue(junit.isPresent(), "Tool 'junit' not found in modules: " + modules); assertJUnitPrintsHelpMessage(junit.get()); } private static URL[] urls(Path directory) { try (var stream = Files.newDirectoryStream(directory, "*.jar")) { var paths = new ArrayList(); stream.forEach(path -> paths.add(url(path))); return paths.toArray(URL[]::new); } catch (Exception e) { throw new AssertionError("Creating URL[] failed: " + e, e); } } private static URL url(Path path) { try { return path.toUri().toURL(); } catch (MalformedURLException e) { throw new AssertionError("Converting path to URL failed: " + e, e); } } private static void assertJUnitPrintsHelpMessage(ToolProvider junit) { var out = new StringWriter(); var err = new StringWriter(); var code = junit.run(new PrintWriter(out), new PrintWriter(err), "--help"); assertAll(() -> assertLinesMatch(List.of( // ">> USAGE >>", // "Launches the JUnit Platform for test discovery and execution.", // ">> OPTIONS >>"), // out.toString().lines().collect(Collectors.toList())), // () -> assertEquals("", err.toString()), // () -> assertEquals(0, code, "Expected exit of 0, but got: " + code) // ); } } VintageGradleIntegrationTests.java000066400000000000000000000045741455764576500410030ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import java.nio.file.Paths; import de.sormuras.bartholdy.Result; import de.sormuras.bartholdy.tool.GradleWrapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; class VintageGradleIntegrationTests { @Test void unsupportedVersion() { var result = run("4.11"); assertThat(result.getExitCode()).isGreaterThan(0); assertThat(result.getOutput("out")) // .doesNotContain("STARTED") // .contains("Unsupported version of junit:junit: 4.11"); } @ParameterizedTest(name = "{0}") @ValueSource(strings = { "4.12", "4.13.2" }) void supportedVersions(String version) { var result = run(version); assertThat(result.getExitCode()).isGreaterThan(0); assertThat(result.getOutput("out")) // .contains("VintageTest > success PASSED") // .contains("VintageTest > failure FAILED"); var testResultsDir = Request.WORKSPACE.resolve("vintage-gradle-" + version).resolve("build/test-results/test"); assertThat(testResultsDir.resolve("TEST-com.example.vintage.VintageTest.xml")).isRegularFile(); } private Result run(String version) { var result = Request.builder() // .setTool(new GradleWrapper(Paths.get(".."))) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .setProject("vintage") // .setWorkspace("vintage-gradle-" + version) // .addArguments("build", "--no-daemon", "--stacktrace") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Djunit4Version=" + version) // .setTimeout(TOOL_TIMEOUT) // .build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); return result; } } VintageMavenIntegrationTests.java000066400000000000000000000046761455764576500406560ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static platform.tooling.support.Helper.TOOL_TIMEOUT; import de.sormuras.bartholdy.Result; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.opentest4j.TestAbortedException; import platform.tooling.support.Helper; import platform.tooling.support.MavenRepo; import platform.tooling.support.Request; class VintageMavenIntegrationTests { @Test void unsupportedVersion() { var result = run("4.11"); assertThat(result.getExitCode()).isEqualTo(0); assertThat(result.getOutput("out")) // .contains("Tests run: 0, Failures: 0, Errors: 0, Skipped: 0"); } @ParameterizedTest(name = "{0}") @ValueSource(strings = { "4.12", "4.13.2" }) void supportedVersions(String version) { var result = run(version); assertThat(result.getExitCode()).isGreaterThan(0); assertThat(result.getOutput("out")) // .contains("Running com.example.vintage.VintageTest") // .contains("VintageTest.failure:") // .contains("Tests run: 2, Failures: 1, Errors: 0, Skipped: 0"); var surefireReportsDir = Request.WORKSPACE.resolve("vintage-maven-" + version).resolve( "target/surefire-reports"); assertThat(surefireReportsDir.resolve("com.example.vintage.VintageTest.txt")).isRegularFile(); assertThat(surefireReportsDir.resolve("TEST-com.example.vintage.VintageTest.xml")).isRegularFile(); } private Result run(String version) { var result = Request.builder() // .setTool(Request.maven()) // .setJavaHome(Helper.getJavaHome("8").orElseThrow(TestAbortedException::new)) // .setProject("vintage") // .setWorkspace("vintage-maven-" + version) // .addArguments("clean", "test", "--update-snapshots", "--batch-mode") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Djunit4Version=" + version) // .setTimeout(TOOL_TIMEOUT) // .build() // .run(); assertFalse(result.isTimedOut(), () -> "tool timed out: " + result); return result; } } XmlAssertions.java000066400000000000000000000205211455764576500356410ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/* * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which * accompanies this distribution and is available at * * https://www.eclipse.org/legal/epl-v20.html */ package platform.tooling.support.tests; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import org.xmlunit.assertj3.XmlAssert; import org.xmlunit.placeholder.PlaceholderDifferenceEvaluator; class XmlAssertions { static void verifyContainsExpectedStartedOpenTestReport(Path testResultsDir) { try (var files = Files.list(testResultsDir)) { Path xmlFile = files.filter(it -> it.getFileName().toString().startsWith("junit-platform-events-")) // .findAny() // .orElseThrow(() -> new AssertionError("Missing open-test-reporting XML file in " + testResultsDir)); verifyContent(xmlFile); } catch (IOException e) { throw new UncheckedIOException(e); } } private static void verifyContent(Path xmlFile) { var expected = """ ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} ${xmlunit.ignore} [engine:junit-jupiter] JUnit Jupiter CONTAINER [engine:junit-jupiter]/[class:com.example.project.CalculatorTests] com.example.project.CalculatorTests CONTAINER [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[method:addsTwoNumbers()] addsTwoNumbers() TEST [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[test-template:add(int, int, int)] add(int, int, int) CONTAINER [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[test-template:add(int, int, int)]/[test-template-invocation:#1] add(int, int, int)[1] TEST [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[test-template:add(int, int, int)]/[test-template-invocation:#2] add(int, int, int)[2] TEST [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[test-template:add(int, int, int)]/[test-template-invocation:#3] add(int, int, int)[3] TEST [engine:junit-jupiter]/[class:com.example.project.CalculatorTests]/[test-template:add(int, int, int)]/[test-template-invocation:#4] add(int, int, int)[4] TEST """; XmlAssert.assertThat(xmlFile).and(expected) // .withDifferenceEvaluator(new PlaceholderDifferenceEvaluator()) // .ignoreWhitespace() // .areIdentical(); } } junit5-r5.10.2/platform-tooling-support-tests/src/test/resources/000077500000000000000000000000001455764576500251565ustar00rootroot00000000000000junit5-r5.10.2/platform-tooling-support-tests/src/test/resources/log4j2-test.xml000066400000000000000000000006721455764576500277630ustar00rootroot00000000000000 junit5-r5.10.2/settings.gradle.kts000066400000000000000000000056221455764576500170540ustar00rootroot00000000000000import buildparameters.BuildParametersExtension import com.gradle.enterprise.gradleplugin.internal.extension.BuildScanExtensionWithHiddenFeatures pluginManagement { includeBuild("gradle/plugins") repositories { gradlePluginPortal() } } plugins { id("junitbuild.build-parameters") id("junitbuild.settings-conventions") } dependencyResolutionManagement { repositories { mavenCentral() maven(url = "https://oss.sonatype.org/content/repositories/snapshots") { mavenContent { snapshotsOnly() } } } } val buildParameters = the() val develocityServer = "https://ge.junit.org" val useDevelocityInstance = !gradle.startParameter.isBuildScan gradleEnterprise { if (useDevelocityInstance) { // Publish to scans.gradle.com when `--scan` is used explicitly server = develocityServer } buildScan { capture.isTaskInputFiles = true isUploadInBackground = !buildParameters.ci if (useDevelocityInstance) { publishAlways() this as BuildScanExtensionWithHiddenFeatures publishIfAuthenticated() } obfuscation { if (buildParameters.ci) { username { "github" } } else { hostname { null } ipAddresses { emptyList() } } } if (buildParameters.junit.develocity.testDistribution.enabled) { tag("test-distribution") } } } buildCache { local { isEnabled = !buildParameters.ci } val buildCacheServer = buildParameters.junit.develocity.buildCache.server if (useDevelocityInstance) { remote(gradleEnterprise.buildCache) { server = buildCacheServer.orNull val authenticated = System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY") != null isPush = buildParameters.ci && authenticated } } else { remote { url = uri(buildCacheServer.getOrElse(develocityServer)).resolve("/cache/") } } } rootProject.name = "junit5" include("documentation") include("junit-jupiter") include("junit-jupiter-api") include("junit-jupiter-engine") include("junit-jupiter-migrationsupport") include("junit-jupiter-params") include("junit-platform-commons") include("junit-platform-console") include("junit-platform-console-standalone") include("junit-platform-engine") include("junit-platform-jfr") include("junit-platform-launcher") include("junit-platform-reporting") include("junit-platform-runner") include("junit-platform-suite") include("junit-platform-suite-api") include("junit-platform-suite-commons") include("junit-platform-suite-engine") include("junit-platform-testkit") include("junit-vintage-engine") include("platform-tests") include("platform-tooling-support-tests") include("junit-bom") // check that every subproject has a custom build file // based on the project name rootProject.children.forEach { project -> project.buildFileName = "${project.name}.gradle.kts" require(project.buildFile.isFile) { "${project.buildFile} must exist" } } enableFeaturePreview("STABLE_CONFIGURATION_CACHE") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")