diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d81c5456c..457b92e79 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ concurrency: jobs: build: - name: Build + name: Build (${{ matrix.runtime }}) runs-on: ${{ matrix.os }} strategy: matrix: @@ -25,12 +25,13 @@ jobs: path: | ~/.m2/repository/* !~/.m2/repository/com/github/cowwoc/requirements - key: ${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }} + key: "${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }}" # Maven command-line options: # --batch-mode: recommended in CI to inform maven to not run in interactive mode (less logs) # -V: strongly recommended in CI, will display the JDK and Maven versions in use. - # Very useful to be quickly sure the selected versions were the ones you think. + # -Dsurefire.useFile=false: useful in CI. Displays test errors in the logs directly (instead of + # having to crawl the workspace files to see the cause). # -e: Display stack-traces on failure - name: Build - run: ./mvnw install --batch-mode -V -e \ No newline at end of file + run: ./mvnw install --batch-mode -V "-Dsurefire.useFile=false" -e \ No newline at end of file diff --git a/.github/workflows/deploy_to_maven_central.yml b/.github/workflows/deploy_to_maven_central.yml index a1525b069..ca077d517 100644 --- a/.github/workflows/deploy_to_maven_central.yml +++ b/.github/workflows/deploy_to_maven_central.yml @@ -1,14 +1,14 @@ -# Source: https://docs.github.com/en/actions/publishing-packages/publishing-java-packages-with-maven +# Based on https://docs.github.com/en/actions/publishing-packages/publishing-java-packages-with-maven +# https://gist.github.com/cstamas/69e6365bbb70521923020d68369bf8e5 and +# https://oss.sonatype.org/nexus-staging-plugin/default/docs/rest.html name: Deploy to Maven Central on: workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true env: - # One can look up a project's profileId by running: - # mvn nexus-staging:rc-list-profiles -DserverId=maven-central-releases -DnexusUrl=https://oss.sonatype.org/ - STAGING_PROFILE_ID: "3799bb102c7f24" + STAGING_HOST: "oss.sonatype.org" OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} @@ -16,13 +16,17 @@ jobs: open-release: runs-on: ubuntu-latest outputs: - INITIAL_REF_POSITION: ${{ steps.open-staging.outputs.INITIAL_REF_POSITION }} - TAG: ${{ steps.open-staging.outputs.TAG }} - STAGING_REPOSITORY_ID: ${{ steps.open-staging.outputs.STAGING_REPOSITORY_ID }} + INITIAL_REF_POSITION: ${{ steps.create-tag.outputs.INITIAL_REF_POSITION }} + TAG: ${{ steps.create-tag.outputs.TAG }} + VERSION: ${{ steps.create-tag.outputs.VERSION }} + STAGING_PROFILE_ID: ${{ steps.parse-profile-id.outputs.STAGING_PROFILE_ID }} + STAGING_REPOSITORY_ID: ${{ steps.parse-repository-id.outputs.STAGING_REPOSITORY_ID }} steps: - uses: actions/checkout@v4 with: ref: ${{ github.ref }} + fetch-depth: 0 + token: ${{ secrets.WORKFLOW_TOKEN }} - uses: actions/setup-java@v4 with: distribution: zulu @@ -33,6 +37,7 @@ jobs: server-password: OSSRH_TOKEN gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Cache Dependencies uses: actions/cache@v4 with: @@ -40,7 +45,7 @@ jobs: path: | ~/.m2/repository/* !~/.m2/repository/com/github/cowwoc/requirements - key: ${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }} + key: "${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }}" - name: Configure Git User run: | @@ -57,26 +62,53 @@ jobs: # # Setting a GitHub Action output parameter: # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter - - name: Open staging repository - id: open-staging + # Extracting the release version number: https://stackoverflow.com/a/16623897/14731 + - name: Create tag + id: create-tag run: | - echo "INITIAL_REF_POSITION=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + echo "INITIAL_REF_POSITION=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" ./mvnw release:prepare --batch-mode -V -e -Darguments="-Ddeploy -Dinvoker.skip=true" - echo "TAG=$(git describe --tag --abbrev=0)" >> $GITHUB_OUTPUT - - output=$(./mvnw --batch-mode -e -DstagingProfileId=${{ env.STAGING_PROFILE_ID }} nexus-staging:rc-open) - [[ "$output" =~ Opened\ (comgithubcowwoc-[[:digit:]]+) ]] - stagingRepositoryId="${BASH_REMATCH[1]}" - echo "STAGING_REPOSITORY_ID=$stagingRepositoryId" >> $GITHUB_OUTPUT + TAG=$(git describe --tag --abbrev=0) + echo "TAG=${TAG}" >> "$GITHUB_OUTPUT" + echo "VERSION=${TAG#"release-"}" >> "$GITHUB_OUTPUT" + + - name: Look up staging profile id + id: request-profile-id + run: > + echo "STAGING_PROFILE_ID=$(curl -u '${{ secrets.OSSRH_USERNAME}}:${{ secrets.OSSRH_TOKEN }}' + -H 'Accept:application/json' + 'https://${{ env.STAGING_HOST }}/service/local/staging/profile_evaluate?t=maven2&g=com.github.cowwoc.requirements&a=anything&v=anything')" + >> "$GITHUB_OUTPUT" + + - name: Parse the staging profile id + id: parse-profile-id + run: > + echo "STAGING_PROFILE_ID=$(echo '${{ steps.request-profile-id.outputs.STAGING_PROFILE_ID }}' | jq -r '.data[0].id')" >> "$GITHUB_OUTPUT" + + - name: Open staging repository + id: open-repository + run: > + echo "STAGING_REPOSITORY_ID=$(curl -u '${{ secrets.OSSRH_USERNAME}}:${{ secrets.OSSRH_TOKEN }}' + -H 'Accept: application/json' + -H 'Content-type: application/json' + -X POST -d '{"data": {"description": "com.googlecode.cmake-maven-project:${{ steps.create-tag.outputs.VERSION }}"}}' + 'https://${{ env.STAGING_HOST }}/service/local/staging/profiles/${{ steps.parse-profile-id.outputs.STAGING_PROFILE_ID }}/start')" + >> "$GITHUB_OUTPUT" + + - name: Parse the staging repository id + id: parse-repository-id + run: > + echo "STAGING_REPOSITORY_ID=$(echo '${{ steps.open-repository.outputs.STAGING_REPOSITORY_ID }}' | jq -r '.data.stagedRepositoryId')" >> "$GITHUB_OUTPUT" deploy: - name: Deploy + name: Deploy (${{ matrix.runtime }}) needs: open-release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ needs.open-release.outputs.TAG }} + token: ${{ secrets.WORKFLOW_TOKEN }} - uses: actions/setup-java@v4 with: distribution: zulu @@ -87,6 +119,7 @@ jobs: server-password: OSSRH_TOKEN gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Cache Dependencies uses: actions/cache@v4 with: @@ -94,12 +127,13 @@ jobs: path: | ~/.m2/repository/* !~/.m2/repository/com/github/cowwoc/requirements - key: ${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }} + key: "${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }}" - name: Deploy to Maven Central run: > - ./mvnw --batch-mode -V -e -Ddeploy -DstagingProfileId=${{ env.STAGING_PROFILE_ID }} - -DstagingRepositoryId=${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }} + ./mvnw --batch-mode -V -e -Ddeploy + -Dstaging_repository_id=${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }} + -Dstaging_host="${{ env.STAGING_HOST }}" deploy close-release: @@ -109,6 +143,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ needs.open-release.outputs.TAG }} + token: ${{ secrets.WORKFLOW_TOKEN }} - uses: actions/setup-java@v4 with: distribution: zulu @@ -119,6 +154,7 @@ jobs: server-password: OSSRH_TOKEN gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Cache Dependencies uses: actions/cache@v4 with: @@ -126,24 +162,26 @@ jobs: path: | ~/.m2/repository/* !~/.m2/repository/com/github/cowwoc/requirements - key: ${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }} + key: "${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }}" - name: Close staging repository run: > - ./mvnw --batch-mode -V -e -DstagingProfileId=${{ env.STAGING_PROFILE_ID }} - -DstagingRepositoryId=${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }} - nexus-staging:rc-close + curl -u ${{ secrets.OSSRH_USERNAME}}:${{ secrets.OSSRH_TOKEN }} -X POST + -H "Content-Type:application/json" + -d '{"data": {"stagedRepositoryId": "${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }}", "description": "Closing repository"}}' + 'https://${{ env.STAGING_HOST }}/service/local/staging/profiles/${{ needs.open-release.outputs.STAGING_PROFILE_ID }}/finish' # Cleanup on failure: https://stackoverflow.com/a/74562058/14731 on-failure: needs: [ open-release, deploy, close-release ] runs-on: ubuntu-latest - if: ${{ always() && contains(needs.*.result, 'failure') }} + if: ${{ failure() || cancelled() }} steps: - uses: actions/checkout@v4 with: ref: ${{ github.ref }} fetch-depth: 0 + token: ${{ secrets.WORKFLOW_TOKEN }} - uses: actions/setup-java@v4 with: distribution: zulu @@ -154,6 +192,7 @@ jobs: server-password: OSSRH_TOKEN gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Cache Dependencies uses: actions/cache@v4 with: @@ -161,13 +200,26 @@ jobs: path: | ~/.m2/repository/* !~/.m2/repository/com/github/cowwoc/requirements - key: ${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }} + key: "${{ runner.OS }}-maven-${{ hashFiles('**/pom.xml') }}" + + - name: Drop staging repository + if: needs.open-release.outputs.STAGING_REPOSITORY_ID != '' + run: > + curl -u ${{ secrets.OSSRH_USERNAME}}:${{ secrets.OSSRH_TOKEN }} -X POST + -H "Content-Type:application/json" + -d '{"data": {"stagedRepositoryId": "${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }}", "description": "Dropping repository"}}' + 'https://${{ env.STAGING_HOST }}/service/local/staging/profiles/${{ needs.open-release.outputs.STAGING_PROFILE_ID }}/drop' - name: Configure Git User run: | git config user.email "cowwoc2020@gmail.com" git config user.name "Gili Tzabari" + - name: Delete tag + if: needs.open-release.outputs.TAG != '' + run: | + git push --delete origin ${{ needs.open-release.outputs.TAG }} + - name: Restore the workflow ref to its original position if: needs.open-release.outputs.INITIAL_REF_POSITION != '' run: | @@ -179,15 +231,3 @@ jobs: fi git push -f origin ${{ github.ref_name }} fi - - - name: Delete tag - if: needs.open-release.outputs.TAG != '' - run: | - git push --delete origin ${{ needs.open-release.outputs.TAG }} - - - name: Drop staging repository - if: needs.open-release.outputs.STAGING_REPOSITORY_ID != '' - run: > - ./mvnw --batch-mode -V -e -DstagingProfileId=${{ env.STAGING_PROFILE_ID }} - -DstagingRepositoryId=${{ needs.open-release.outputs.STAGING_REPOSITORY_ID }} - nexus-staging:rc-drop \ No newline at end of file diff --git a/LICENSE-3RD-PARTY.md b/LICENSE-3RD-PARTY.md index ae1007835..a1b70263c 100644 --- a/LICENSE-3RD-PARTY.md +++ b/LICENSE-3RD-PARTY.md @@ -17,7 +17,6 @@ * [J2ObjC Annotations](https://github.com/google/j2objc/) * [java-diff-utils](https://github.com/java-diff-utils/java-diff-utils/java-diff-utils) * [Byte Buddy (without dependencies)](https://bytebuddy.net/byte-buddy) - * [Byte Buddy (without dependencies)](https://bytebuddy.net/byte-buddy) * [Apache Commons Math](http://commons.apache.org/proper/commons-math/) * [AssertJ Core](https://assertj.github.io/doc/#assertj-core) * [testng](https://testng.org) diff --git a/benchmark/guava/src/test/java/module-info.java b/benchmark/guava/src/test/java/module-info.java index e24dc295f..b9c179a56 100644 --- a/benchmark/guava/src/test/java/module-info.java +++ b/benchmark/guava/src/test/java/module-info.java @@ -4,6 +4,7 @@ requires com.google.common; requires org.testng; requires com.github.cowwoc.requirements.guava; + requires static com.google.errorprone.annotations; exports com.github.cowwoc.requirements.benchmark.guava to org.testng; exports com.github.cowwoc.requirements.benchmark.guava.jmh_generated to jmh.core; diff --git a/benchmark/pom.xml b/benchmark/pom.xml index dfee7e9a1..32321affe 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -24,8 +24,7 @@ -Xdiags:verbose -Werror - -Xlint:all,-module,-requires-automatic,-processing - -implicit:class + -Xlint:all,-requires-automatic,-processing diff --git a/docs/Changelog.md b/docs/Changelog.md index 27455a6d9..e04911842 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,18 +1,18 @@ Minor updates involving cosmetic changes have been omitted from this list. See https://github.com/cowwoc/requirements.java/commits/master for a full list. -## Version 9.0.0 - ? +## Version 9.0.0 - 2024/05/23 * Breaking changes: 1. The library now requires JDK 21. 2. Added a `jackson` module to validate `JsonNode`. 3. Removed the Maven plugin and code generator. - * The code generator was causing a "split package" issue because code was always being generated into - the same package. + * The code generator was causing a "split package" issue because it was generating code into the same + package in all dependent libraries. * This caused a “split package” error since only one module is allowed to export a package. 4. Removed the use of native binaries. Colored DIFFs are still supported, but Windows requires the use of Windows Terminal (free download in Windows 10, built-in feature in Windows 11). - 5. Renamed `validateThat()` to `checkIf()`. + 5. Replaced `validateThat()` with `checkIf()`. 6. Replaced `assertThat()` with `assert assumeThat().elseThrow()`. 7. Added support for the built-in `assert` mechanism. - Asserts can be used with any type of validator, but are typically used @@ -23,8 +23,9 @@ See https://github.com/cowwoc/requirements.java/commits/master for a full list. validation results. 10. Renamed `Validator.getActual()` to `getValue()`. 11. Replaced `isBetweenClosed(min, max)` with `isBetween(min, true, max, true)`. - 12. Renamed `StringValidator.isInteger()` to `isInt()` and `isCharacter()` to `isChar()`. - 13. Improved performance by reducing memory usage and the frequency of GC runs. + 12. Renamed `StringValidator.isInteger()` to `asPrimitiveInteger()` and `isCharacter()` + to `asPrimitiveCharacter()`. + 13. Improved performance by reducing memory allocation and the frequency of GC runs. 14. Added support for primitive types to avoid boxing when possible. 15. Dropped the `isOneOf()` and `isNotOneOf()` functionality yet again. I haven't figured out a good design for this yet. diff --git a/guava/pom.xml b/guava/pom.xml index 48a91f468..a60deb90f 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -30,8 +30,6 @@ -Xdiags:verbose -Werror -Xlint:all,-requires-automatic,-requires-transitive-automatic,-module,-try - - -Xpkginfo:always diff --git a/jackson/pom.xml b/jackson/pom.xml index 5be88795c..535220800 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -30,8 +30,6 @@ -Xdiags:verbose -Werror -Xlint:all,-requires-automatic,-requires-transitive-automatic,-module,-try - - -Xpkginfo:always @@ -54,7 +52,7 @@ - https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.17.0/ + https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.17.1/ - net.sourceforge.pmd - pmd-compat6 - ${pmd.version} - net.sourceforge.pmd pmd-core @@ -301,33 +294,6 @@ release-@{project.version} - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - maven-central-releases - https://oss.sonatype.org/ - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.12.1 - - true - true - - -Xdiags:verbose - -Werror - - - org.apache.maven.plugins maven-javadoc-plugin @@ -420,7 +386,6 @@ true false - true 21 @@ -437,10 +402,6 @@ deploy - deploy @@ -451,7 +412,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 attach-sources @@ -469,7 +430,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + 3.2.4 sign-artifacts @@ -484,26 +445,20 @@ + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + true + + + maven-central-releases::https://${staging_host}/service/local/staging/deployByRepositoryId/${staging_repository_id} + + + - - no-deploy - - - - !deploy - - - - test - benchmark - - \ No newline at end of file diff --git a/test/src/test/java/com/github/cowwoc/requirements/test/java/ObjectTest.java b/test/src/test/java/com/github/cowwoc/requirements/test/java/ObjectTest.java index 5acb880b1..1923edd38 100644 --- a/test/src/test/java/com/github/cowwoc/requirements/test/java/ObjectTest.java +++ b/test/src/test/java/com/github/cowwoc/requirements/test/java/ObjectTest.java @@ -427,7 +427,7 @@ public void isInt() try (ApplicationScope scope = new TestApplicationScope(NONE)) { Object actual = 5; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").isInt(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").isInteger(); } } @@ -437,7 +437,7 @@ public void isInt_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { Object actual = (short) 5; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").isInt(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").isInteger(); } } @@ -527,7 +527,7 @@ public void isChar() try (ApplicationScope scope = new TestApplicationScope(NONE)) { Object actual = '5'; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").isChar(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").isCharacter(); } } @@ -537,7 +537,7 @@ public void isChar_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { Object actual = true; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").isChar(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").isCharacter(); } } diff --git a/test/src/test/java/com/github/cowwoc/requirements/test/java/StringTest.java b/test/src/test/java/com/github/cowwoc/requirements/test/java/StringTest.java index 73c70fad6..5251c82d2 100644 --- a/test/src/test/java/com/github/cowwoc/requirements/test/java/StringTest.java +++ b/test/src/test/java/com/github/cowwoc/requirements/test/java/StringTest.java @@ -662,7 +662,7 @@ public void stringAsByte() { byte expected = (byte) 1; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asByte().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveByte().isEqualTo(expected); } } @@ -672,7 +672,7 @@ public void stringAsByte_Overflow() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf(Byte.MAX_VALUE + 1); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asByte(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveByte(); } } @@ -682,19 +682,31 @@ public void stringAsByte_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf(Byte.MAX_VALUE + 1); - byte value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asByte(). + byte value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveByte(). getValueOrDefault((byte) 5); requireThat(value, "value").isEqualTo((byte) 5); } } + @Test + public void stringAsByte_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = String.valueOf(Byte.MAX_VALUE + 1); + Byte value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveByte().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = IllegalArgumentException.class) public void stringAsByte_False() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asByte(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveByte(); } } @@ -704,7 +716,7 @@ public void nullAsByte() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asByte(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveByte(); } } @@ -715,7 +727,7 @@ public void stringAsShort() { short expected = (short) 1; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asShort().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveShort().isEqualTo(expected); } } @@ -725,7 +737,7 @@ public void stringAsShort_Overflow() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf(Short.MAX_VALUE + 1); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asShort(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveShort(); } } @@ -735,19 +747,31 @@ public void stringAsShort_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf(Short.MAX_VALUE + 1); - short value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asShort(). + short value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveShort(). getValueOrDefault((short) 10); requireThat(value, "value").isEqualTo((short) 10); } } + @Test + public void stringAsShort_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = String.valueOf(Short.MAX_VALUE + 1); + Short value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveShort().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = IllegalArgumentException.class) public void stringAsShort_False() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asShort(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveShort(); } } @@ -757,7 +781,7 @@ public void nullAsShort() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asShort(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveShort(); } } @@ -768,7 +792,7 @@ public void stringAsInteger() { Integer expected = Short.MAX_VALUE + 1; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asInteger().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveInteger().isEqualTo(expected); } } @@ -778,7 +802,7 @@ public void stringAsInteger_Overflow() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf((long) Integer.MAX_VALUE + 1); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asInteger(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveInteger(); } } @@ -788,19 +812,31 @@ public void stringAsInteger_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = String.valueOf((long) Integer.MAX_VALUE + 1); - int value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asInteger(). + int value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveInteger(). getValueOrDefault(15); requireThat(value, "value").isEqualTo(15); } } + @Test + public void stringAsInteger_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = String.valueOf((long) Integer.MAX_VALUE + 1); + Integer value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveInteger().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = IllegalArgumentException.class) public void stringAsInteger_False() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asInteger(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveInteger(); } } @@ -810,7 +846,7 @@ public void nullAsInteger() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asInteger(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveInteger(); } } @@ -821,7 +857,7 @@ public void stringAsLong() { Long expected = (long) Integer.MAX_VALUE + 1; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asLong().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveLong().isEqualTo(expected); } } @@ -831,7 +867,7 @@ public void stringAsLong_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asLong(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveLong(); } } @@ -841,19 +877,31 @@ public void stringAsLong_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - long value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asLong(). + long value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveLong(). getValueOrDefault(20); requireThat(value, "value").isEqualTo(20); } } + @Test + public void stringAsLong_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = "not a number"; + Long value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveLong().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = NullPointerException.class) public void nullAsLong() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asLong(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveLong(); } } @@ -864,7 +912,7 @@ public void stringAsFloat() { Float expected = 1.234f; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asFloat().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveFloat().isEqualTo(expected); } } @@ -874,7 +922,7 @@ public void stringAsFloat_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asFloat(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveFloat(); } } @@ -884,19 +932,31 @@ public void stringAsFloat_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - float value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asFloat(). + float value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveFloat(). getValueOrDefault(0.5f); requireThat(value, "value").isEqualTo(0.5f); } } + @Test + public void stringAsFloat_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = "not a number"; + Float value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveFloat().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = NullPointerException.class) public void nullAsFloat() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asFloat(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveFloat(); } } @@ -907,7 +967,7 @@ public void stringAsDouble() { Double expected = 1.234; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asDouble().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveDouble().isEqualTo(expected); } } @@ -917,7 +977,7 @@ public void stringAsDouble_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asDouble(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveDouble(); } } @@ -927,19 +987,31 @@ public void stringAsDouble_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - double value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asDouble(). + double value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveDouble(). getValueOrDefault(0.1); requireThat(value, "value").isEqualTo(0.1); } } + @Test + public void stringAsDouble_getValueOrNull() + { + try (ApplicationScope scope = new TestApplicationScope(NONE)) + { + String actual = "not a number"; + Double value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveDouble().asBoxed(). + getValueOrDefault(null); + requireThat(value, "value").isEqualTo(null); + } + } + @Test(expectedExceptions = NullPointerException.class) public void nullAsDouble() { try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asDouble(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveDouble(); } } @@ -950,7 +1022,7 @@ public void stringAsBoolean() { Boolean expected = true; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asBoolean().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveBoolean().isEqualTo(expected); } } @@ -961,7 +1033,7 @@ public void stringAsBoolean_False() { String actual = "not a boolean"; // Boolean.parseBoolean() returns false for any string that is not equal to "true" - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asBoolean().isFalse(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveBoolean().isFalse(); } } @@ -971,7 +1043,7 @@ public void nullAsBoolean() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asBoolean(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveBoolean(); } } @@ -982,7 +1054,7 @@ public void stringAsCharacter() { char expected = 'c'; String actual = String.valueOf(expected); - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asCharacter().isEqualTo(expected); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveCharacter().isEqualTo(expected); } } @@ -992,7 +1064,7 @@ public void stringAsCharacter_False() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a char"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asCharacter(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveCharacter(); } } @@ -1002,7 +1074,7 @@ public void nullAsCharacter() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = null; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asCharacter(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveCharacter(); } } @@ -1012,7 +1084,7 @@ public void stringAsCharacter_getValueOrDefault() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = ""; - char value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asCharacter(). + char value = new TestValidatorsImpl(scope).checkIf(actual, "Actual").asPrimitiveCharacter(). getValueOrDefault('/'); requireThat(value, "value").isEqualTo('/'); } diff --git a/test/src/test/java/com/github/cowwoc/requirements/test/java/internal/diff/DiffTest.java b/test/src/test/java/com/github/cowwoc/requirements/test/java/internal/diff/DiffTest.java index db8f5cbfb..dd45929cc 100644 --- a/test/src/test/java/com/github/cowwoc/requirements/test/java/internal/diff/DiffTest.java +++ b/test/src/test/java/com/github/cowwoc/requirements/test/java/internal/diff/DiffTest.java @@ -918,7 +918,7 @@ public void stringAsInteger_NoDiff() try (ApplicationScope scope = new TestApplicationScope(NONE)) { String actual = "not a number"; - new TestValidatorsImpl(scope).requireThat(actual, "Actual").asInteger(); + new TestValidatorsImpl(scope).requireThat(actual, "Actual").asPrimitiveInteger(); assert (false) : "Expected validator to throw an exception"; } catch (IllegalArgumentException e) diff --git a/test/src/test/java/module-info.java b/test/src/test/java/module-info.java index abea28aa0..7ad55aeab 100644 --- a/test/src/test/java/module-info.java +++ b/test/src/test/java/module-info.java @@ -10,6 +10,7 @@ requires com.github.cowwoc.requirements.guava; requires com.github.cowwoc.requirements.jackson; requires com.fasterxml.jackson.databind; + requires static com.google.errorprone.annotations; exports com.github.cowwoc.requirements.test to org.testng; exports com.github.cowwoc.requirements.test.guava to org.testng;