diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..eaeceeea --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +* text=auto eol=lf +gradlew text eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf +gradle-wrapper.jar -text -diff -merge -filter \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c9b2105b..519d9124 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,7 +4,7 @@ updates: directory: "/" schedule: interval: "weekly" - - package-ecosystem: "maven" + - package-ecosystem: "gradle" directory: "/" schedule: interval: "weekly" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98352d0f..b154bfde 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,53 +3,49 @@ on: milestone: types: [closed] jobs: - build: + release: name: Release ${{ github.event.milestone.title }} runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: master fetch-depth: 0 + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v5 - name: Set up Git run: | git config user.name "Zonky Bot" git config user.email "bot@zonky.com" - - name: Set up JDK - uses: actions/setup-java@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v5 with: distribution: 'zulu' - java-version: 8 - server-id: ossrh - server-username: MAVEN_USER - server-password: MAVEN_PASS - gpg-private-key: ${{ secrets.SIGNING_CERT }} - gpg-passphrase: SIGNING_PASS - - name: Release with Maven + java-version: '17' + cache: 'gradle' + - name: Make Gradle wrapper executable + run: chmod +x gradlew + - name: Publish to Maven Central via Gradle env: RELEASE_VERSION: ${{ github.event.milestone.title }} - MAVEN_USER: ${{ secrets.MAVEN_USER }} - MAVEN_PASS: ${{ secrets.MAVEN_PASS }} - SIGNING_PASS: ${{ secrets.SIGNING_PASS }} - run: mvn -B release:prepare release:perform -DreleaseVersion=$RELEASE_VERSION - - name: Upload staged artifacts to Central Sonatype + # Gradle signing plugin (build.gradle.kts) + MAVEN_SIGNING_KEY: ${{ secrets.SIGNING_CERT }} + MAVEN_SIGNING_PASSPHRASE: ${{ secrets.SIGNING_PASS }} + # nmcp credentials (build.gradle.kts) + USERNAME_TOKEN: ${{ secrets.MAVEN_USER }} + PASSWORD_TOKEN: ${{ secrets.MAVEN_PASS }} + # Use the milestone title as the build's version without touching gradle.properties + run: | + ./gradlew \ + -Pversion=$RELEASE_VERSION \ + clean check publishAllPublicationsToCentralPortal \ + --stacktrace + # Reproduces Maven Release Plugin’s v@{project.version} tag + - name: Tag release + if: success() env: - SONATYPE_USERNAME: ${{ secrets.MAVEN_USER }} - SONATYPE_PASSWORD: ${{ secrets.MAVEN_PASS }} + RELEASE_VERSION: ${{ github.event.milestone.title }} run: | - SONATYPE_TOKEN=$(printf "$SONATYPE_USERNAME:$SONATYPE_PASSWORD" | base64) - PUBLISH_NAMESPACE="io.zonky" - echo "Uploading artifacts from OSSRH-Staging to Central Sonatype..." - RESPONSE=$(curl -s -w "%{http_code}" -o response_body.txt -X POST \ - -H "Authorization: Bearer $SONATYPE_TOKEN" \ - "https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/$PUBLISH_NAMESPACE?publishing_type=user_managed") - if [ "$RESPONSE" -ne 200 ]; then - echo "Failed to upload artifacts to Central Sonatype. Response code: $RESPONSE. Response body: " - cat response_body.txt - echo "Visit https://central.sonatype.com/publishing/deployments for more information." - exit 1 - else - echo "Artifacts were uploaded successfully to Central Sonatype." - echo "Visit https://central.sonatype.com/publishing/deployments to view your artifacts." - fi + git tag "v$RELEASE_VERSION" + git push origin "v$RELEASE_VERSION" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84b53f3a..c178b8ea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,15 +6,19 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11, 17, 21, 22] # LTS and newer versions + java: [17, 21, 25] # LTS and newer versions steps: - - name: Checkout project - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: ${{ matrix.java }} - cache: 'maven' - - name: Build with Maven - run: mvn -B test + - name: Checkout project + uses: actions/checkout@v5 + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v5 + - name: Set up JDK + uses: actions/setup-java@v5 + with: + distribution: 'zulu' + java-version: ${{ matrix.java }} + cache: 'gradle' + - name: Make Gradle wrapper executable + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew check diff --git a/.gitignore b/.gitignore index 481a27f1..a1c2952f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ target/ .project .settings dist/ +.gradle/ +build/ +out/ +classes/ \ No newline at end of file diff --git a/HEADER b/HEADER new file mode 100644 index 00000000..17f32874 --- /dev/null +++ b/HEADER @@ -0,0 +1,13 @@ +Copyright ${CREATION_YEAR} Tomas Vanek + +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. \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..df6a23c3 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,181 @@ +import enforcer.rules.DependencyConvergence +import org.apache.tools.ant.taskdefs.condition.Os + +plugins { + `java-library` + `maven-publish` + signing + pmd + id("dev.yumi.gradle.licenser") + id("com.gradleup.nmcp") + id("de.aaschmid.cpd") + id("org.kordamp.gradle.project-enforcer") +} + +val projectName = providers.gradleProperty("name") +val projectGroup = providers.gradleProperty("group") +val projectVersion = providers.gradleProperty("version") + +val javaVersion = providers.gradleProperty("java_version") + +val embeddedPostgresBinariesVersion = providers.gradleProperty("embedded_postgres_binaries_version") +val commonsCodecVersion = providers.gradleProperty("commons_codec_version") +val commonsCompressVersion = providers.gradleProperty("commons_compress_version") +val commonsIoVersion = providers.gradleProperty("commons_io_version") +val commonsLang3Version = providers.gradleProperty("commons_lang3_version") +val flywayVersion = providers.gradleProperty("flyway_version") +val junit4Version = providers.gradleProperty("junit4_version") +val junit5Version = providers.gradleProperty("junit5_version") +val liquibaseVersion = providers.gradleProperty("liquibase_version") +val mockitoVersion = providers.gradleProperty("mockito_version") +val pmdVersion = providers.gradleProperty("pmd_version") +val postgresqlVersion = providers.gradleProperty("postgresql_version") +val slf4jVersion = providers.gradleProperty("slf4j_version") +val xzVersion = providers.gradleProperty("xz_version") + +description = "Embedded PostgreSQL Server" +base.archivesName = projectName.get() +group = projectGroup.get() +version = projectVersion.get() + +repositories { mavenCentral() } + +dependencies { + runtimeOnly("io.zonky.test.postgres:embedded-postgres-binaries-windows-amd64:${embeddedPostgresBinariesVersion.get()}") + runtimeOnly("io.zonky.test.postgres:embedded-postgres-binaries-darwin-amd64:${embeddedPostgresBinariesVersion.get()}") + runtimeOnly("io.zonky.test.postgres:embedded-postgres-binaries-linux-amd64:${embeddedPostgresBinariesVersion.get()}") + runtimeOnly("io.zonky.test.postgres:embedded-postgres-binaries-linux-amd64-alpine:${embeddedPostgresBinariesVersion.get()}") + + implementation("org.slf4j:slf4j-api:${slf4jVersion.get()}") + implementation("org.apache.commons:commons-lang3:${commonsLang3Version.get()}") + implementation("org.apache.commons:commons-compress:${commonsCompressVersion.get()}") + implementation("org.tukaani:xz:${xzVersion.get()}") + implementation("commons-io:commons-io:${commonsIoVersion.get()}") + implementation("commons-codec:commons-codec:${commonsCodecVersion.get()}") + implementation("org.postgresql:postgresql:${postgresqlVersion.get()}") + + compileOnly("org.flywaydb:flyway-core:${flywayVersion.get()}") + compileOnly("org.liquibase:liquibase-core:${liquibaseVersion.get()}") + compileOnly("junit:junit:${junit4Version.get()}") + compileOnly("org.junit.jupiter:junit-jupiter-api:${junit5Version.get()}") + + testImplementation("org.flywaydb:flyway-core:${flywayVersion.get()}") + testImplementation("org.liquibase:liquibase-core:${liquibaseVersion.get()}") + testImplementation(platform("org.junit:junit-bom:${junit5Version.get()}")) + testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation("junit:junit:${junit4Version.get()}") + testImplementation("org.mockito:mockito-core:${mockitoVersion.get()}") + + testRuntimeOnly("org.junit.vintage:junit-vintage-engine") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testRuntimeOnly("org.slf4j:slf4j-simple:${slf4jVersion.get()}") +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(javaVersion.get()) + sourceCompatibility = JavaVersion.toVersion(javaVersion.get().toInt()) + targetCompatibility = JavaVersion.toVersion(javaVersion.get().toInt()) + withSourcesJar() + withJavadocJar() +} +tasks { + withType().configureEach { + options.encoding = "UTF-8" + options.compilerArgs.add("-Xlint:deprecation") + sourceCompatibility = javaVersion.get() + targetCompatibility = javaVersion.get() + if (javaVersion.get().toInt() > 8) options.release = javaVersion.get().toInt() + } + withType().configureEach { + options.encoding = "UTF-8" + val standardOptions = options as StandardJavadocDocletOptions + standardOptions.addStringOption("Xdoclint:none", "-quiet") + } + withType().configureEach { defaultCharacterEncoding = "UTF-8" } + withType().configureEach { + defaultCharacterEncoding = "UTF-8" + useJUnitPlatform() + if (!Os.isFamily(Os.FAMILY_WINDOWS)) environment("LC_ALL", System.getenv("LC_ALL") ?: "en_US.UTF-8") + } + named("check") { dependsOn("cpdCheck") } +} +pmd { + toolVersion = pmdVersion.get() + isConsoleOutput = true + isIgnoreFailures = false + rulesMinimumPriority = 4 +} +cpd { + toolVersion = pmdVersion.get() + isIgnoreFailures = true + minimumTokenCount = 100 + encoding = "UTF-8" +} +enforce { + rule(DependencyConvergence::class.java) { + failOnDynamicVersions = true + failOnChangingVersions = true + failOnNonReproducibleResolution = true + } +} +license { + rule(file("./HEADER")) + include("**/*.java") + exclude("**/*.properties") +} +publishing { + publications { + create("maven") { + from(components["java"]) + groupId = project.group.toString() + artifactId = base.archivesName.get() + version = project.version.toString() + pom { + name = projectName + description = project.description + url = "https://github.com/zonkyio/embedded-postgres" + + licenses { + license { + name = "The Apache License, Version 2.0" + url = "https://www.apache.org/licenses/LICENSE-2.0.txt" + distribution = "repo" + } + } + developers { + developer { + name = "Tomas Vanek" + email = "tomix26@gmail.com" + } + developer { + name = "Zonky Developers" + email = "developers@zonky.cz" + } + } + scm { + url = "https://github.com/zonkyio/embedded-postgres" + connection = "scm:git:https://github.com/zonkyio/embedded-postgres.git" + developerConnection = "scm:git:https://github.com/zonkyio/embedded-postgres.git" + tag = "HEAD" + } + } + } + } +} +signing { + val signingKey = System.getenv("MAVEN_SIGNING_KEY") + val signingPassphrase = System.getenv("MAVEN_SIGNING_PASSPHRASE") + if (!signingKey.isNullOrBlank()) { + isRequired = true + useInMemoryPgpKeys(signingKey, signingPassphrase) + sign(publishing.publications) + } else { + isRequired = false + } +} +nmcp { + publishAllPublicationsToCentralPortal { + username = System.getenv("USERNAME_TOKEN") ?: "" + password = System.getenv("PASSWORD_TOKEN") ?: "" + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..eb27cf96 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,54 @@ +########################################################################## +# Standard Properties +org.gradle.jvmargs = -Xmx1G -Dfile.encoding=UTF-8 +org.gradle.warning.mode = all +org.gradle.configuration-cache = false +########################################################################## +# Maven Properties +group = io.zonky.test +name = embedded-postgres +version = 2.1.2-SNAPSHOT +########################################################################## +# Java Version +java_version = 8 +########################################################################## +# Dependency Versions +# Check this on https://central.sonatype.com/artifact/io.zonky.test.postgres/embedded-postgres-binaries-bom/ +embedded_postgres_binaries_version = 14.19.0 +# Check this on https://central.sonatype.com/artifact/commons-codec/commons-codec/ +commons_codec_version = 1.19.0 +# Check this on https://central.sonatype.com/artifact/org.apache.commons/commons-compress/ +commons_compress_version = 1.28.0 +# Check this on https://central.sonatype.com/artifact/commons-io/commons-io/ +commons_io_version = 2.21.0 +# Check this on https://central.sonatype.com/artifact/org.apache.commons/commons-lang3/ +commons_lang3_version = 3.19.0 +# Check this on https://central.sonatype.com/artifact/org.flywaydb/flyway-core/ +flyway_version = 9.22.3 +# Check this on https://central.sonatype.com/artifact/org.junit.jupiter/junit-jupiter-api/ +junit5_version = 5.14.1 +# Check this on https://central.sonatype.com/artifact/junit/junit/ +junit4_version = 4.13.2 +# Check this on https://central.sonatype.com/artifact/org.liquibase/liquibase-core/ +liquibase_version = 4.33.0 +# Check this on https://central.sonatype.com/artifact/org.mockito/mockito-core/ +mockito_version = 4.11.0 +# Check this on https://central.sonatype.com/artifact/net.sourceforge.pmd/pmd/ +pmd_version = 7.18.0 +# Check this on https://central.sonatype.com/artifact/org.postgresql/postgresql/ +postgresql_version = 42.7.8 +# Check this on https://central.sonatype.com/artifact/org.slf4j/slf4j-api/ +slf4j_version = 1.7.36 +# Check this on https://central.sonatype.com/artifact/org.tukaani/xz/ +xz_version = 1.10 +########################################################################## +# Plugin Versions +# Check this on https://plugins.gradle.org/plugin/dev.yumi.gradle.licenser/ +yumi_gradle_licenser_version = 2.2.1 +# Check this on https://github.com/GradleUp/nmcp/releases/latest/ +nmcp_version = 1.2.0 +# Check this on https://github.com/aaschmid/gradle-cpd-plugin/releases/latest/ +cpd_version = 3.5 +# Check this on https://github.com/kordamp/enforcer-gradle-plugin/releases/latest/ +enforcer_gradle_version = 0.14.0 +########################################################################## diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..8bdaf60c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..6954be87 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..adff685a --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original 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. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# 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 ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# 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 + if ! command -v java >/dev/null 2>&1 + then + 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 +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..c4bdd3ab --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +@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 +@rem SPDX-License-Identifier: Apache-2.0 +@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=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@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% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 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! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 7ba63380..00000000 --- a/pom.xml +++ /dev/null @@ -1,384 +0,0 @@ - - - - - 4.0.0 - - io.zonky.test - embedded-postgres - 2.1.2-SNAPSHOT - - embedded-postgres - Embedded PostgreSQL Server - - - 1.8 - 1.8 - - UTF-8 - UTF-8 - - 14.19.0 - 1.17.1 - 1.26.2 - 2.16.1 - 3.18.0 - 9.22.3 - 5.10.5 - 4.13.2 - 4.30.0 - 4.11.0 - 7.4.0 - 42.7.7 - 1.7.36 - 1.10 - 3.5.0 - 1.6 - 3.8.0 - 3.24.0 - 3.1.1 - 3.3.1 - 3.3.1 - - - https://github.com/zonkyio/embedded-postgres - - - scm:git:https://github.com/zonkyio/embedded-postgres.git - scm:git:https://github.com/zonkyio/embedded-postgres.git - https://github.com/zonkyio/embedded-postgres - HEAD - - - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - Tomas Vanek - tomix26@gmail.com - - - Zonky Developers - developers@zonky.cz - - - - - - ossrh - https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/ - - - ossrh - https://central.sonatype.com/repository/maven-snapshots/ - - - - - - - commons-io - commons-io - ${commons-io.version} - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - org.apache.commons - commons-compress - ${commons-compress.version} - - - commons-codec - commons-codec - ${commons-codec.version} - - - org.junit - junit-bom - ${junit5.version} - pom - import - - - - - - io.zonky.test.postgres - embedded-postgres-binaries-windows-amd64 - ${embedded-postgres-binaries.version} - runtime - - - io.zonky.test.postgres - embedded-postgres-binaries-darwin-amd64 - ${embedded-postgres-binaries.version} - runtime - - - io.zonky.test.postgres - embedded-postgres-binaries-linux-amd64 - ${embedded-postgres-binaries.version} - runtime - - - io.zonky.test.postgres - embedded-postgres-binaries-linux-amd64-alpine - ${embedded-postgres-binaries.version} - runtime - - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.apache.commons - commons-lang3 - - - org.apache.commons - commons-compress - - - org.tukaani - xz - ${xz.version} - - - commons-io - commons-io - - - commons-codec - commons-codec - - - org.flywaydb - flyway-core - ${flyway.version} - true - - - org.liquibase - liquibase-core - ${liquibase.version} - true - - - org.postgresql - postgresql - ${postgresql.version} - - - junit - junit - ${junit4.version} - provided - true - - - org.junit.jupiter - junit-jupiter-api - provided - true - - - org.junit.vintage - junit-vintage-engine - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - - org.slf4j - slf4j-simple - ${slf4j.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - ${maven-enforcer-plugin.version} - - - enforce-versions - validate - - enforce - - - - - - - - - - - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - ${env.LC_ALL} - - - - - maven-pmd-plugin - ${maven-pmd-plugin.version} - - - verify - - check - - - - - - net.sourceforge.pmd - pmd-core - ${pmd.version} - compile - - - net.sourceforge.pmd - pmd-java - ${pmd.version} - compile - - - - false - true - 1.8 - UTF-8 - 100 - 4 - - - - org.apache.maven.plugins - maven-source-plugin - ${maven-source-plugin.version} - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin.version} - - - attach-javadocs - - jar - - - - - none - - - - org.apache.maven.plugins - maven-release-plugin - ${maven-release-plugin.version} - - false - release - v@{project.version} - - - - - - - - - default-lc-all - - - !env.LC_ALL - - - Unix - - - - en_US.UTF-8 - - - - release - - - - org.apache.maven.plugins - maven-gpg-plugin - ${maven-gpg-plugin.version} - - - sign-artifacts - verify - - sign - - - - - --pinentry-mode - loopback - - - - - - - - - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..50ffa18f --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,19 @@ +val name = providers.gradleProperty("name") +rootProject.name = name.get() + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } + val yumiGradleLicenserVersion = providers.gradleProperty("yumi_gradle_licenser_version") + val nmcpVersion = providers.gradleProperty("nmcp_version") + val cpdVersion = providers.gradleProperty("cpd_version") + val enforcerGradleVersion = providers.gradleProperty("enforcer_gradle_version") + plugins { + id("dev.yumi.gradle.licenser").version(yumiGradleLicenserVersion.get()) + id("com.gradleup.nmcp").version(nmcpVersion.get()) + id("de.aaschmid.cpd").version(cpdVersion.get()) + id("org.kordamp.gradle.project-enforcer").version(enforcerGradleVersion.get()) + } +} diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/ConnectionInfo.java b/src/main/java/io/zonky/test/db/postgres/embedded/ConnectionInfo.java index acef3179..1722beb1 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/ConnectionInfo.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/ConnectionInfo.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import java.util.HashMap; @@ -26,6 +29,7 @@ public class ConnectionInfo { private final String user; private final Map properties; + @SuppressWarnings("unused") public ConnectionInfo(final String dbName, final int port, final String user) { this(dbName, port, user, emptyMap()); } diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/DatabaseConnectionPreparer.java b/src/main/java/io/zonky/test/db/postgres/embedded/DatabaseConnectionPreparer.java index 30577f8b..33789008 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/DatabaseConnectionPreparer.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/DatabaseConnectionPreparer.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; -import javax.sql.DataSource; - public interface DatabaseConnectionPreparer extends DatabasePreparer { @Override diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/DatabasePreparer.java b/src/main/java/io/zonky/test/db/postgres/embedded/DatabasePreparer.java index 432c09c1..b385dc1f 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/DatabasePreparer.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/DatabasePreparer.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.zonky.test.db.postgres.embedded; -import java.sql.SQLException; +package io.zonky.test.db.postgres.embedded; import javax.sql.DataSource; +import java.sql.SQLException; /** * A DatabasePreparer applies an arbitrary set of changes * (e.g. database migrations, user creation) to a database * before it is presented to the user. - * + *

* The preparation steps are expected to be deterministic. * For efficiency reasons, databases created by DatabasePreparer * instances may be pooled, using {@link Object#hashCode()} and diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/DefaultPostgresBinaryResolver.java b/src/main/java/io/zonky/test/db/postgres/embedded/DefaultPostgresBinaryResolver.java index b90fda68..3e4ced37 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/DefaultPostgresBinaryResolver.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/DefaultPostgresBinaryResolver.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import io.zonky.test.db.postgres.util.ArchUtils; import io.zonky.test.db.postgres.util.LinuxUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +49,8 @@ public InputStream getPgBinary(String system, String machineHardware) throws IOE String architecture = ArchUtils.normalize(machineHardware); String distribution = LinuxUtils.getDistributionName(); - logger.info("Detected distribution: '{}'", Optional.ofNullable(distribution).orElse("Unknown")); + if (logger.isInfoEnabled()) + logger.info("Detected distribution: '{}'", Optional.ofNullable(distribution).orElse("Unknown")); if (distribution != null) { Resource resource = findPgBinary(normalize(format("postgres-%s-%s-%s.txz", system, architecture, distribution))); @@ -63,8 +68,8 @@ public InputStream getPgBinary(String system, String machineHardware) throws IOE return resource.getInputStream(); } - if ((StringUtils.equals(system, "Darwin") && StringUtils.equals(machineHardware, "aarch64")) // NOPMD - || (StringUtils.equals(system, "Windows") && StringUtils.equals(architecture, "arm_64"))) { // NOPMD + if ((Strings.CS.equals(system, "Darwin") && Strings.CS.equals(machineHardware, "aarch64")) + || (Strings.CS.equals(system, "Windows") && Strings.CS.equals(architecture, "arm_64"))) { resource = findPgBinary(normalize(format("postgres-%s-%s.txz", system, "x86_64"))); if (resource != null) { logger.warn("No native binaries supporting ARM architecture found. " + @@ -81,9 +86,10 @@ public InputStream getPgBinary(String system, String machineHardware) throws IOE throw new IllegalStateException("Missing embedded postgres binaries"); } + @SuppressWarnings("PMD.AvoidLiteralsInIfCondition") private static Resource findPgBinary(String resourceLocation) throws IOException { logger.trace("Searching for postgres binaries - location: '{}'", resourceLocation); - ClassLoader classLoader = DefaultPostgresBinaryResolver.class.getClassLoader(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); List urls = Collections.list(classLoader.getResources(resourceLocation)); if (urls.size() > 1) { @@ -120,8 +126,7 @@ public InputStream getInputStream() throws IOException { URLConnection con = this.url.openConnection(); try { return con.getInputStream(); - } - catch (IOException ex) { + } catch (IOException ex) { // Close the HTTP connection (if applicable). if (con instanceof HttpURLConnection) { ((HttpURLConnection) con).disconnect(); diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/EmbeddedPostgres.java b/src/main/java/io/zonky/test/db/postgres/embedded/EmbeddedPostgres.java index 48fe5843..844dbb41 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/EmbeddedPostgres.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/EmbeddedPostgres.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import io.zonky.test.db.postgres.util.LinuxUtils; @@ -28,22 +31,13 @@ import org.tukaani.xz.XZInputStream; import javax.sql.DataSource; -import java.io.ByteArrayInputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousFileChannel; -import java.nio.channels.Channel; -import java.nio.channels.CompletionHandler; -import java.nio.channels.FileLock; -import java.nio.channels.OverlappingFileLockException; +import java.nio.channels.*; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -55,17 +49,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; import java.util.concurrent.Phaser; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -79,8 +64,7 @@ import static java.util.Collections.unmodifiableMap; @SuppressWarnings("PMD.AvoidDuplicateLiterals") // "postgres" -public class EmbeddedPostgres implements Closeable -{ +public class EmbeddedPostgres implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(EmbeddedPostgres.class); private static final String JDBC_FORMAT = "jdbc:postgresql://localhost:%s/%s?user=%s"; @@ -93,7 +77,8 @@ public class EmbeddedPostgres implements Closeable private final File pgDir; private final Duration pgStartupWait; - private final File dataDirectory, lockFile; + private final File dataDirectory; + private final File lockFile; private final UUID instanceId = UUID.randomUUID(); private final int port; private final AtomicBoolean started = new AtomicBoolean(); @@ -104,6 +89,7 @@ public class EmbeddedPostgres implements Closeable private final Map connectConfig; private volatile FileOutputStream lockStream; + @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName") private volatile FileLock lock; private final boolean cleanDataDirectory; @@ -111,20 +97,20 @@ public class EmbeddedPostgres implements Closeable private final ProcessBuilder.Redirect outputRedirector; private final Process process; + @SuppressWarnings("unused") EmbeddedPostgres(File parentDirectory, File dataDirectory, boolean cleanDataDirectory, Map postgresConfig, Map localeConfig, int port, Map connectConfig, - PgBinaryResolver pgBinaryResolver, ProcessBuilder.Redirect errorRedirector, ProcessBuilder.Redirect outputRedirector) throws IOException - { + PgBinaryResolver pgBinaryResolver, ProcessBuilder.Redirect errorRedirector, ProcessBuilder.Redirect outputRedirector) throws IOException { this(parentDirectory, dataDirectory, cleanDataDirectory, postgresConfig, localeConfig, port, connectConfig, pgBinaryResolver, errorRedirector, outputRedirector, DEFAULT_PG_STARTUP_WAIT, null, null); } + @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") EmbeddedPostgres(File parentDirectory, File dataDirectory, boolean cleanDataDirectory, - Map postgresConfig, Map localeConfig, int port, Map connectConfig, - PgBinaryResolver pgBinaryResolver, ProcessBuilder.Redirect errorRedirector, - ProcessBuilder.Redirect outputRedirector, Duration pgStartupWait, - File overrideWorkingDirectory, Consumer dataDirectoryCustomizer) throws IOException - { + Map postgresConfig, Map localeConfig, int port, Map connectConfig, + PgBinaryResolver pgBinaryResolver, ProcessBuilder.Redirect errorRedirector, + ProcessBuilder.Redirect outputRedirector, Duration pgStartupWait, + File overrideWorkingDirectory, Consumer dataDirectoryCustomizer) throws IOException { this.cleanDataDirectory = cleanDataDirectory; this.postgresConfig = new HashMap<>(postgresConfig); this.localeConfig = new HashMap<>(localeConfig); @@ -168,17 +154,17 @@ public class EmbeddedPostgres implements Closeable this.process = startPostmaster(); } + @SuppressWarnings("unused") public Process getProcess() { - return this.process; + return this.process; } - public DataSource getTemplateDatabase() - { + public DataSource getTemplateDatabase() { return getDatabase("postgres", "template1"); } - public DataSource getTemplateDatabase(Map properties) - { + @SuppressWarnings("unused") + public DataSource getTemplateDatabase(Map properties) { return getDatabase("postgres", "template1", properties); } @@ -186,8 +172,8 @@ public DataSource getPostgresDatabase() { return getDatabase("postgres", "postgres"); } - public DataSource getPostgresDatabase(Map properties) - { + @SuppressWarnings("unused") + public DataSource getPostgresDatabase(Map properties) { return getDatabase("postgres", "postgres", properties); } @@ -195,11 +181,10 @@ public DataSource getDatabase(String userName, String dbName) { return getDatabase(userName, dbName, connectConfig); } - public DataSource getDatabase(String userName, String dbName, Map properties) - { + public DataSource getDatabase(String userName, String dbName, Map properties) { final PGSimpleDataSource ds = new PGSimpleDataSource(); - ds.setServerName("localhost"); - ds.setPortNumber(port); + ds.setServerNames(new String[]{"localhost"}); + ds.setPortNumbers(new int[]{port}); ds.setDatabaseName(dbName); ds.setUser(userName); @@ -213,23 +198,20 @@ public DataSource getDatabase(String userName, String dbName, Map getConnectConfig() - { + Map getConnectConfig() { return unmodifiableMap(connectConfig); } - private static int detectPort() throws IOException - { + private static int detectPort() throws IOException { try (ServerSocket socket = new ServerSocket(0)) { while (!socket.isBound()) { Thread.sleep(50); @@ -241,16 +223,15 @@ private static int detectPort() throws IOException } } - private void lock() throws IOException - { + @SuppressWarnings("PMD.AssignmentInOperand") + private void lock() throws IOException { lockStream = new FileOutputStream(lockFile); if ((lock = lockStream.getChannel().tryLock()) == null) { throw new IllegalStateException("could not lock " + lockFile); } } - private void initdb() - { + private void initdb() { final StopWatch watch = new StopWatch(); watch.start(); List args = new ArrayList<>(); @@ -262,16 +243,14 @@ private void initdb() LOG.info("{} initdb completed in {}", instanceId, watch); } - private Process startPostmaster() throws IOException - { + private Process startPostmaster() throws IOException { final StopWatch watch = new StopWatch(); watch.start(); if (started.getAndSet(true)) { throw new IllegalStateException("Postmaster already started"); } - final List args = new ArrayList<>(); - args.addAll(Arrays.asList( + final List args = new ArrayList<>(Arrays.asList( "-D", dataDirectory.getPath(), "-o", String.join(" ", createInitOptions()), "-w", "start" @@ -289,7 +268,7 @@ private Process startPostmaster() throws IOException ProcessOutputLogger.logOutput(LOG, postmaster, POSTGRES.processName()); } - LOG.info("{} postmaster started as {} on port {}. Waiting up to {} for server startup to finish.", instanceId, postmaster.toString(), port, pgStartupWait); + LOG.info("{} postmaster started as {} on port {}. Waiting up to {} for server startup to finish.", instanceId, postmaster, port, pgStartupWait); Runtime.getRuntime().addShutdownHook(newCloserThread()); @@ -297,15 +276,12 @@ private Process startPostmaster() throws IOException return postmaster; } - private List createInitOptions() - { - final List initOptions = new ArrayList<>(); - initOptions.addAll(Arrays.asList( + private List createInitOptions() { + final List initOptions = new ArrayList<>(Arrays.asList( "-p", Integer.toString(port), "-F")); - for (final Entry config : postgresConfig.entrySet()) - { + for (final Entry config : postgresConfig.entrySet()) { initOptions.add("-c"); initOptions.add(config.getKey() + "=" + config.getValue()); } @@ -313,8 +289,7 @@ private List createInitOptions() return initOptions; } - private List createLocaleOptions() - { + private List createLocaleOptions() { final List localeOptions = new ArrayList<>(); for (final Entry config : localeConfig.entrySet()) { localeOptions.add(String.format("--%s=%s", config.getKey(), config.getValue())); @@ -322,8 +297,7 @@ private List createLocaleOptions() return localeOptions; } - private void waitForServerStartup(StopWatch watch) throws IOException - { + private void waitForServerStartup(StopWatch watch) throws IOException { Throwable lastCause = null; final long start = System.nanoTime(); final long maxWaitNs = TimeUnit.NANOSECONDS.convert(pgStartupWait.toMillis(), TimeUnit.MILLISECONDS); @@ -347,8 +321,8 @@ private void waitForServerStartup(StopWatch watch) throws IOException throw new IOException("Gave up waiting for server to start after " + pgStartupWait.toMillis() + "ms", lastCause); } - private void verifyReady() throws SQLException - { + @SuppressWarnings({"PMD.AvoidLiteralsInIfCondition", "SqlNoDataSourceInspection"}) + private void verifyReady() throws SQLException { final InetAddress localhost = InetAddress.getLoopbackAddress(); try (Socket sock = new Socket()) { sock.setSoTimeout((int) Duration.ofMillis(500).toMillis()); @@ -358,8 +332,7 @@ private void verifyReady() throws SQLException } try (Connection c = getPostgresDatabase().getConnection() ; Statement s = c.createStatement() ; - ResultSet rs = s.executeQuery("SELECT 1")) - { + ResultSet rs = s.executeQuery("SELECT 1")) { if (!rs.next()) { throw new IllegalStateException("expecting single row"); } @@ -372,27 +345,21 @@ private void verifyReady() throws SQLException } } - private Thread newCloserThread() - { - final Thread closeThread = new Thread(new Runnable() { - @Override - public void run() - { - try { - EmbeddedPostgres.this.close(); - } - catch (IOException ex) { - LOG.error("Unexpected IOException from Closeables.close", ex); - } + private Thread newCloserThread() { + final Thread closeThread = new Thread(() -> { + try { + EmbeddedPostgres.this.close(); + } catch (IOException ex) { + LOG.error("Unexpected IOException from Closeables.close", ex); } }); closeThread.setName("postgres-" + instanceId + "-closer"); return closeThread; } + @SuppressWarnings("PMD.AvoidCatchingGenericException") @Override - public void close() throws IOException - { + public void close() throws IOException { if (closed.getAndSet(true)) { return; } @@ -402,7 +369,7 @@ public void close() throws IOException pgCtl(dataDirectory, "stop"); LOG.info("{} shut down postmaster in {}", instanceId, watch); } catch (final Exception e) { - LOG.error("Could not stop postmaster " + instanceId, e); + LOG.error("Could not stop postmaster {}", instanceId, e); } if (lock != null) { lock.release(); @@ -424,10 +391,9 @@ public void close() throws IOException } } - private void pgCtl(File dir, String action) - { - final List args = new ArrayList<>(); - args.addAll(Arrays.asList( + @SuppressWarnings("SameParameterValue") + private void pgCtl(File dir, String action) { + final List args = new ArrayList<>(Arrays.asList( "-D", dir.getPath(), action, "-m", PG_STOP_MODE, "-t", PG_STOP_WAIT_S, "-w" @@ -435,14 +401,13 @@ private void pgCtl(File dir, String action) system(PG_CTL, args); } - private void cleanOldDataDirectories(File parentDirectory) - { + @SuppressWarnings("PMD.AvoidCatchingGenericException") + private void cleanOldDataDirectories(File parentDirectory) { final File[] children = parentDirectory.listFiles(); if (children == null) { return; } - for (final File dir : children) - { + for (final File dir : children) { if (!dir.isDirectory()) { continue; } @@ -453,7 +418,7 @@ private void cleanOldDataDirectories(File parentDirectory) continue; } try (FileOutputStream fos = new FileOutputStream(lockFile); - FileLock lock = fos.getChannel().tryLock()) { + FileLock lock = fos.getChannel().tryLock()) { if (lock != null) { LOG.info("Found stale data directory {}", dir); if (new File(dir, "postmaster.pid").exists()) { @@ -462,9 +427,9 @@ private void cleanOldDataDirectories(File parentDirectory) LOG.info("Shut down orphaned postmaster!"); } catch (Exception e) { if (LOG.isDebugEnabled()) { - LOG.warn("Failed to stop postmaster " + dir, e); + LOG.warn("Failed to stop postmaster {}", dir, e); } else { - LOG.warn("Failed to stop postmaster " + dir + ": " + e.getMessage()); + LOG.warn("Failed to stop postmaster {}: {}", dir, e.getMessage()); } } } @@ -479,24 +444,20 @@ private void cleanOldDataDirectories(File parentDirectory) } } - private static File getWorkingDirectory() - { + private static File getWorkingDirectory() { final File tempWorkingDirectory = new File(System.getProperty("java.io.tmpdir"), "embedded-pg"); return new File(System.getProperty("ot.epg.working-dir", tempWorkingDirectory.getPath())); } - public static EmbeddedPostgres start() throws IOException - { + public static EmbeddedPostgres start() throws IOException { return builder().start(); } - public static EmbeddedPostgres.Builder builder() - { + public static EmbeddedPostgres.Builder builder() { return new Builder(); } - public static class Builder - { + public static class Builder { private final File parentDirectory = getWorkingDirectory(); private File overrideWorkingDirectory; private File builderDataDirectory; @@ -518,15 +479,17 @@ public static class Builder config.put("max_connections", "300"); } + @SuppressWarnings("UnusedReturnValue") public Builder setPGStartupWait(Duration pgStartupWait) { Objects.requireNonNull(pgStartupWait); if (pgStartupWait.isNegative()) { - throw new IllegalArgumentException("Negative durations are not permitted."); + throw new IllegalArgumentException("Negative durations are not permitted."); } this.pgStartupWait = pgStartupWait; return this; } + @SuppressWarnings("unused") public Builder setCleanDataDirectory(boolean cleanDataDirectory) { builderCleanDataDirectory = cleanDataDirectory; return this; @@ -541,46 +504,54 @@ public Builder setDataDirectory(File directory) { return this; } + @SuppressWarnings("unused") public Builder setDataDirectory(String path) { return setDataDirectory(new File(path)); } + @SuppressWarnings("unused") public Builder setServerConfig(String key, String value) { config.put(key, value); return this; } + @SuppressWarnings("unused") public Builder setLocaleConfig(String key, String value) { localeConfig.put(key, value); return this; } + @SuppressWarnings("UnusedReturnValue") public Builder setConnectConfig(String key, String value) { connectConfig.put(key, value); return this; } + @SuppressWarnings("unused") public Builder setOverrideWorkingDirectory(File workingDirectory) { overrideWorkingDirectory = workingDirectory; return this; } + @SuppressWarnings("unused") public Builder setPort(int port) { builderPort = port; return this; } + @SuppressWarnings("unused") public Builder setErrorRedirector(ProcessBuilder.Redirect errRedirector) { this.errRedirector = errRedirector; return this; } - public Builder setOutputRedirector(ProcessBuilder.Redirect outRedirector) - { + @SuppressWarnings("unused") + public Builder setOutputRedirector(ProcessBuilder.Redirect outRedirector) { this.outRedirector = outRedirector; return this; } + @SuppressWarnings("unused") public Builder setPgBinaryResolver(PgBinaryResolver pgBinaryResolver) { this.pgBinaryResolver = pgBinaryResolver; return this; @@ -592,8 +563,7 @@ public Builder setDataDirectoryCustomizer(final Consumer dataDirectoryCust } public EmbeddedPostgres start() throws IOException { - if (builderPort == 0) - { + if (builderPort == 0) { builderPort = detectPort(); } if (builderDataDirectory == null) { @@ -625,7 +595,7 @@ public boolean equals(Object o) { Objects.equals(errRedirector, builder.errRedirector) && Objects.equals(outRedirector, builder.outRedirector) && Objects.equals(dataDirectoryCustomizer != null ? dataDirectoryCustomizer.getClass() : null, - builder.dataDirectoryCustomizer != null ? builder.dataDirectoryCustomizer.getClass() : null); + builder.dataDirectoryCustomizer != null ? builder.dataDirectoryCustomizer.getClass() : null); } @Override @@ -634,8 +604,8 @@ public int hashCode() { } } - private void system(Command command, List args) - { + @SuppressWarnings("PMD.AvoidCatchingGenericException") + private void system(Command command, List args) { try { final ProcessBuilder builder = new ProcessBuilder(); @@ -652,15 +622,14 @@ private void system(Command command, List args) if (0 != process.waitFor()) { throw new IllegalStateException(String.format("Process %s failed", builder.command())); } - } catch (final RuntimeException e) { // NOPMD + } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new RuntimeException(e); } } - private static void mkdirs(File dir) - { + private static void mkdirs(File dir) { if (!dir.mkdirs() && !(dir.isDirectory() && dir.exists())) { throw new IllegalStateException("could not create " + dir); } @@ -674,8 +643,7 @@ private static void mkdirs(File dir) * * @return Current operating system string. */ - private static String getOS() - { + private static String getOS() { if (SystemUtils.IS_OS_WINDOWS) { return "Windows"; } @@ -693,18 +661,18 @@ private static String getOS() * * @return Current machine architecture string. */ - private static String getArchitecture() - { + private static String getArchitecture() { return "amd64".equals(SystemUtils.OS_ARCH) ? "x86_64" : SystemUtils.OS_ARCH; } /** - * Unpack archive compressed by tar with xz compression. By default system tar is used (faster). If not found, then the + * Unpack archive compressed by tar with xz compression. By default, system tar is used (faster). If not found, then the * java implementation takes place. * * @param stream A stream with the postgres binaries. * @param targetDir The directory to extract the content to. */ + @SuppressWarnings({"PMD.AssignmentInOperand", "PMD.CloseResource", "ResultOfMethodCallIgnored"}) private static void extractTxz(InputStream stream, File targetDir) throws IOException { try ( XZInputStream xzIn = new XZInputStream(stream); @@ -714,7 +682,7 @@ private static void extractTxz(InputStream stream, File targetDir) throws IOExce final Phaser phaser = new Phaser(1); TarArchiveEntry entry; - while ((entry = tarIn.getNextTarEntry()) != null) { + while ((entry = tarIn.getNextEntry()) != null) { final String individualFile = entry.getName(); final File fsObject = new File(targetDir, individualFile); @@ -787,8 +755,8 @@ private void closeChannel(Channel channel) { } } - private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File overrideWorkingDirectory) - { + @SuppressWarnings({"PMD.AssignmentInOperand", "PMD.CloseResource", "ResultOfMethodCallIgnored"}) + private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File overrideWorkingDirectory) { PREPARE_BINARIES_LOCK.lock(); try { if (PREPARE_BINARIES.containsKey(pgBinaryResolver) && PREPARE_BINARIES.get(pgBinaryResolver).exists()) { @@ -812,7 +780,7 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over } try (DigestInputStream pgArchiveData = new DigestInputStream(pgBinary, MessageDigest.getInstance("MD5")); - ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ByteArrayOutputStream baos = new ByteArrayOutputStream()) { IOUtils.copy(pgArchiveData, baos); pgArchiveData.close(); @@ -828,7 +796,7 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over if (!isPgBinReady(pgDirExists)) { File unpackLockFile = new File(pgDir, LOCK_FILE_NAME); try (FileOutputStream lockStream = new FileOutputStream(unpackLockFile); - FileLock unpackLock = lockStream.getChannel().tryLock()) { + FileLock unpackLock = lockStream.getChannel().tryLock()) { if (unpackLock != null) { LOG.info("Extracting Postgres..."); try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) { @@ -868,6 +836,7 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over } } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private static boolean isPgBinReady(File pgDirExists) { if (!pgDirExists.exists()) { return false; @@ -881,8 +850,7 @@ private static boolean isPgBinReady(File pgDirExists) { } @Override - public String toString() - { + public String toString() { return "EmbeddedPG-" + instanceId; } diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/FlywayPreparer.java b/src/main/java/io/zonky/test/db/postgres/embedded/FlywayPreparer.java index f7fecf4d..83379662 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/FlywayPreparer.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/FlywayPreparer.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import org.apache.commons.lang3.reflect.MethodUtils; @@ -18,12 +21,7 @@ import org.flywaydb.core.api.configuration.FluentConfiguration; import javax.sql.DataSource; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; public final class FlywayPreparer implements DatabasePreparer { @@ -62,8 +60,9 @@ private FlywayPreparer(FluentConfiguration configuration, List locations this.properties = properties; } + @SuppressWarnings("PMD.AvoidCatchingGenericException") @Override - public void prepare(DataSource ds) throws SQLException { + public void prepare(DataSource ds) { configuration.dataSource(ds); Flyway flyway = configuration.load(); try { diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/LiquibasePreparer.java b/src/main/java/io/zonky/test/db/postgres/embedded/LiquibasePreparer.java index d611681e..66eec754 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/LiquibasePreparer.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/LiquibasePreparer.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import liquibase.Contexts; @@ -19,11 +22,12 @@ import liquibase.database.jvm.JdbcConnection; import liquibase.exception.LiquibaseException; import liquibase.resource.ClassLoaderResourceAccessor; -import liquibase.resource.FileSystemResourceAccessor; +import liquibase.resource.DirectoryResourceAccessor; import liquibase.resource.ResourceAccessor; import javax.sql.DataSource; import java.io.File; +import java.io.FileNotFoundException; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; @@ -55,7 +59,11 @@ public static LiquibasePreparer forFile(File file, Contexts contexts) { if (dir == null) throw new IllegalArgumentException("Cannot get parent dir from file"); - return new LiquibasePreparer(file.getName(), new FileSystemResourceAccessor(dir), contexts); + try { + return new LiquibasePreparer(file.getName(), new DirectoryResourceAccessor(dir), contexts); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } } private LiquibasePreparer(String location, ResourceAccessor accessor, Contexts contexts) { @@ -64,10 +72,11 @@ private LiquibasePreparer(String location, ResourceAccessor accessor, Contexts c this.contexts = contexts != null ? contexts : new Contexts(); } + @SuppressWarnings("PMD.CloseResource") @Override public void prepare(DataSource ds) throws SQLException { - try (Connection connection = ds.getConnection()) { - Database database = getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection)); + try (Connection connection = ds.getConnection(); + Database database = getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection))) { Liquibase liquibase = new Liquibase(location, accessor, database); liquibase.update(contexts); } catch (LiquibaseException e) { diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/PgBinaryResolver.java b/src/main/java/io/zonky/test/db/postgres/embedded/PgBinaryResolver.java index 2102ab7c..b2f49143 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/PgBinaryResolver.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/PgBinaryResolver.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -26,7 +28,7 @@ public interface PgBinaryResolver { /** * Returns an input stream with the postgress binary for the given - * systen and hardware architecture. + * system and hardware architecture. * @param system a system identification (Darwin, Linux...) * @param machineHardware a machine hardware architecture (x86_64...) * @return the binary diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/PreparedDbProvider.java b/src/main/java/io/zonky/test/db/postgres/embedded/PreparedDbProvider.java index 0e306cc5..ed369cfa 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/PreparedDbProvider.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/PreparedDbProvider.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import io.zonky.test.db.postgres.embedded.EmbeddedPostgres.Builder; @@ -22,13 +25,8 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.SynchronousQueue; @@ -38,8 +36,7 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableMap; -public class PreparedDbProvider -{ +public class PreparedDbProvider { private static final String JDBC_FORMAT = "jdbc:postgresql://localhost:%d/%s?user=%s"; /** @@ -51,6 +48,7 @@ public class PreparedDbProvider private final PrepPipeline dbPreparer; + @SuppressWarnings({"unused", "PMD.AvoidDuplicateLiterals"}) public static PreparedDbProvider forPreparer(DatabasePreparer preparer) { return forPreparer(preparer, Collections.emptyList()); } @@ -71,8 +69,8 @@ private PreparedDbProvider(DatabasePreparer preparer, Iterable * Each schema set has its own database cluster. The template1 database has the schema preloaded so that * each test case need only create a new database and not re-invoke your preparer. */ - private static synchronized PrepPipeline createOrFindPreparer(DatabasePreparer preparer, Iterable> customizers) throws IOException, SQLException - { + @SuppressWarnings("PMD.CloseResource") + private static synchronized PrepPipeline createOrFindPreparer(DatabasePreparer preparer, Iterable> customizers) throws IOException, SQLException { final ClusterKey key = new ClusterKey(preparer, customizers); PrepPipeline result = CLUSTERS.get(key); if (result != null) { @@ -93,8 +91,7 @@ private static synchronized PrepPipeline createOrFindPreparer(DatabasePreparer p * Create a new database, and return it as a JDBC connection string. * NB: No two invocations will return the same database. */ - public String createDatabase() throws SQLException - { + public String createDatabase() throws SQLException { return getJdbcUri(createNewDB()); } @@ -105,25 +102,22 @@ public String createDatabase() throws SQLException * get the JDBC connection string. * NB: No two invocations will return the same database. */ - private DbInfo createNewDB() throws SQLException - { - return dbPreparer.getNextDb(); + private DbInfo createNewDB() throws SQLException { + return dbPreparer.getNextDb(); } - public ConnectionInfo createNewDatabase() throws SQLException - { + public ConnectionInfo createNewDatabase() throws SQLException { final DbInfo dbInfo = createNewDB(); - return dbInfo == null || !dbInfo.isSuccess() ? null : new ConnectionInfo(dbInfo.getDbName(), dbInfo.getPort(), dbInfo.getUser(), dbInfo.getProperties()); + return !dbInfo.isSuccess() ? null : new ConnectionInfo(dbInfo.getDbName(), dbInfo.getPort(), dbInfo.getUser(), dbInfo.getProperties()); } /** * Create a new Datasource given DBInfo. * More common usage is to call createDatasource(). */ - public DataSource createDataSourceFromConnectionInfo(final ConnectionInfo connectionInfo) throws SQLException - { + public DataSource createDataSourceFromConnectionInfo(final ConnectionInfo connectionInfo) throws SQLException { final PGSimpleDataSource ds = new PGSimpleDataSource(); - ds.setPortNumber(connectionInfo.getPort()); + ds.setPortNumbers(new int[]{connectionInfo.getPort()}); ds.setDatabaseName(connectionInfo.getDbName()); ds.setUser(connectionInfo.getUser()); @@ -139,13 +133,12 @@ public DataSource createDataSourceFromConnectionInfo(final ConnectionInfo connec * Create a new database, and return it as a DataSource. * No two invocations will return the same database. */ - public DataSource createDataSource() throws SQLException - { + @SuppressWarnings("unused") + public DataSource createDataSource() throws SQLException { return createDataSourceFromConnectionInfo(createNewDatabase()); } - private String getJdbcUri(DbInfo db) - { + private String getJdbcUri(DbInfo db) { String additionalParameters = db.getProperties().entrySet().stream() .map(e -> String.format("&%s=%s", e.getKey(), e.getValue())) .collect(Collectors.joining()); @@ -155,8 +148,8 @@ private String getJdbcUri(DbInfo db) /** * Return configuration tweaks in a format appropriate for otj-jdbc DatabaseModule. */ - public Map getConfigurationTweak(String dbModuleName) throws SQLException - { + @SuppressWarnings("unused") + public Map getConfigurationTweak(String dbModuleName) throws SQLException { final DbInfo db = dbPreparer.getNextDb(); final Map result = new HashMap<>(); result.put("ot.db." + dbModuleName + ".uri", getJdbcUri(db)); @@ -168,18 +161,15 @@ public Map getConfigurationTweak(String dbModuleName) throws SQL * Spawns a background thread that prepares databases ahead of time for speed, and then uses a * synchronous queue to hand the prepared databases off to test cases. */ - private static class PrepPipeline implements Runnable - { + private static class PrepPipeline implements Runnable { private final EmbeddedPostgres pg; - private final SynchronousQueue nextDatabase = new SynchronousQueue(); + private final SynchronousQueue nextDatabase = new SynchronousQueue<>(); - PrepPipeline(EmbeddedPostgres pg) - { + PrepPipeline(EmbeddedPostgres pg) { this.pg = pg; } - PrepPipeline start() - { + PrepPipeline start() { final ExecutorService service = Executors.newSingleThreadExecutor(r -> { final Thread t = new Thread(r); t.setDaemon(true); @@ -191,8 +181,7 @@ PrepPipeline start() return this; } - DbInfo getNextDb() throws SQLException - { + DbInfo getNextDb() throws SQLException { try { final DbInfo next = nextDatabase.take(); if (next.ex != null) { @@ -206,10 +195,9 @@ DbInfo getNextDb() throws SQLException } @Override - public void run() - { + public void run() { while (true) { - final String newDbName = RandomStringUtils.randomAlphabetic(12).toLowerCase(Locale.ENGLISH); + final String newDbName = RandomStringUtils.secure().nextAlphabetic(12).toLowerCase(Locale.ENGLISH); SQLException failure = null; try { create(pg.getPostgresDatabase(), newDbName, "postgres"); @@ -230,8 +218,8 @@ public void run() } } - private static void create(final DataSource connectDb, final String dbName, final String userName) throws SQLException - { + @SuppressWarnings("SameParameterValue") + private static void create(final DataSource connectDb, final String dbName, final String userName) throws SQLException { if (dbName == null) { throw new IllegalStateException("the database name must not be null!"); } @@ -240,7 +228,7 @@ private static void create(final DataSource connectDb, final String dbName, fina } try (Connection c = connectDb.getConnection(); - PreparedStatement stmt = c.prepareStatement(String.format("CREATE DATABASE %s OWNER %s ENCODING = 'utf8'", dbName, userName))) { + PreparedStatement stmt = c.prepareStatement(String.format("CREATE DATABASE %s OWNER %s ENCODING = 'utf8'", dbName, userName))) { stmt.execute(); } } @@ -275,8 +263,8 @@ public int hashCode() { } } - public static class DbInfo - { + public static class DbInfo { + @SuppressWarnings("unused") public static DbInfo ok(final String dbName, final int port, final String user) { return ok(dbName, port, user, emptyMap()); } diff --git a/src/main/java/io/zonky/test/db/postgres/embedded/ProcessOutputLogger.java b/src/main/java/io/zonky/test/db/postgres/embedded/ProcessOutputLogger.java index 708a685f..009d642b 100644 --- a/src/main/java/io/zonky/test/db/postgres/embedded/ProcessOutputLogger.java +++ b/src/main/java/io/zonky/test/db/postgres/embedded/ProcessOutputLogger.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.embedded; import org.slf4j.Logger; @@ -70,16 +73,17 @@ static void logOutput(final Logger logger, final Process process, final String p t.start(); } + @SuppressWarnings({"PMD.AvoidAccessibilityAlteration", "PMD.AvoidCatchingGenericException", "PMD.AvoidCatchingThrowable", "JavaLangInvokeHandleSignature"}) private static String processId(Process process) { try { // java 9+ return String.format("pid(%s)", MethodHandles.lookup().findVirtual(Process.class, "pid", MethodType.methodType(long.class)).invoke(process)); - } catch (Throwable ignored) {} // NOPMD since MethodHandles.invoke throws Throwable + } catch (Throwable ignored) {} try { // openjdk / oraclejdk 8 final Field pid = process.getClass().getDeclaredField("pid"); pid.setAccessible(true); return String.format("pid(%s)", pid.getInt(process)); - } catch (Exception ignored) {} // NOPMD + } catch (Exception ignored) {} return String.format("id(%s)", process.hashCode()); } diff --git a/src/main/java/io/zonky/test/db/postgres/junit/EmbeddedPostgresRules.java b/src/main/java/io/zonky/test/db/postgres/junit/EmbeddedPostgresRules.java index dd31423d..c1824d4b 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit/EmbeddedPostgresRules.java +++ b/src/main/java/io/zonky/test/db/postgres/junit/EmbeddedPostgresRules.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.DatabasePreparer; import org.junit.rules.TestRule; public final class EmbeddedPostgresRules { - private EmbeddedPostgresRules() { - } + private EmbeddedPostgresRules() {} /** * Create a vanilla Postgres cluster -- just initialized, no customizations applied. @@ -31,8 +33,7 @@ public static SingleInstancePostgresRule singleInstance() { * Returns a {@link TestRule} to create a Postgres cluster, shared amongst all test cases in this JVM. * The rule contributes Config switches to configure each test case to get its own database. */ - public static PreparedDbRule preparedDatabase(DatabasePreparer preparer) - { + public static PreparedDbRule preparedDatabase(DatabasePreparer preparer) { return new PreparedDbRule(preparer); } } diff --git a/src/main/java/io/zonky/test/db/postgres/junit/PreparedDbRule.java b/src/main/java/io/zonky/test/db/postgres/junit/PreparedDbRule.java index 9fc2b671..8c139dbb 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit/PreparedDbRule.java +++ b/src/main/java/io/zonky/test/db/postgres/junit/PreparedDbRule.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,13 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.zonky.test.db.postgres.junit; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; -import javax.sql.DataSource; +package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.ConnectionInfo; import io.zonky.test.db.postgres.embedded.DatabasePreparer; @@ -25,6 +22,11 @@ import io.zonky.test.db.postgres.embedded.PreparedDbProvider; import org.junit.rules.ExternalResource; +import javax.sql.DataSource; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; + public class PreparedDbRule extends ExternalResource { private final DatabasePreparer preparer; @@ -56,6 +58,7 @@ protected void before() throws Throwable { dataSource = provider.createDataSourceFromConnectionInfo(connectionInfo); } + @SuppressWarnings("PMD.NullAssignment") @Override protected void after() { dataSource = null; @@ -64,9 +67,9 @@ protected void after() { } public DataSource getTestDatabase() { - if (dataSource == null) { - throw new AssertionError("not initialized"); - } + if (dataSource == null) { + throw new AssertionError("not initialized"); + } return dataSource; } diff --git a/src/main/java/io/zonky/test/db/postgres/junit/SingleInstancePostgresRule.java b/src/main/java/io/zonky/test/db/postgres/junit/SingleInstancePostgresRule.java index ea2bb5d7..02d4b2a7 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit/SingleInstancePostgresRule.java +++ b/src/main/java/io/zonky/test/db/postgres/junit/SingleInstancePostgresRule.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,8 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; +import io.zonky.test.db.postgres.embedded.EmbeddedPostgres; +import org.junit.rules.ExternalResource; + import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; @@ -20,20 +26,15 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; -import io.zonky.test.db.postgres.embedded.EmbeddedPostgres; -import org.junit.rules.ExternalResource; - -public class SingleInstancePostgresRule extends ExternalResource -{ +public class SingleInstancePostgresRule extends ExternalResource { private volatile EmbeddedPostgres epg; private volatile Connection postgresConnection; private final List> builderCustomizers = new CopyOnWriteArrayList<>(); - SingleInstancePostgresRule() { } + SingleInstancePostgresRule() {} @Override - protected void before() throws Throwable - { + protected void before() throws Throwable { super.before(); epg = pg(); postgresConnection = epg.getPostgresDatabase().getConnection(); @@ -45,6 +46,7 @@ private EmbeddedPostgres pg() throws IOException { return builder.start(); } + @SuppressWarnings("unused") public SingleInstancePostgresRule customize(Consumer customizer) { if (epg != null) { throw new AssertionError("already started"); @@ -53,8 +55,7 @@ public SingleInstancePostgresRule customize(Consumer c return this; } - public EmbeddedPostgres getEmbeddedPostgres() - { + public EmbeddedPostgres getEmbeddedPostgres() { EmbeddedPostgres epg = this.epg; if (epg == null) { throw new AssertionError("JUnit test not started yet!"); @@ -63,8 +64,7 @@ public EmbeddedPostgres getEmbeddedPostgres() } @Override - protected void after() - { + protected void after() { try { postgresConnection.close(); } catch (SQLException e) { diff --git a/src/main/java/io/zonky/test/db/postgres/junit5/EmbeddedPostgresExtension.java b/src/main/java/io/zonky/test/db/postgres/junit5/EmbeddedPostgresExtension.java index 2cb49ce0..a75b9ca5 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit5/EmbeddedPostgresExtension.java +++ b/src/main/java/io/zonky/test/db/postgres/junit5/EmbeddedPostgresExtension.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.DatabasePreparer; @@ -31,8 +34,7 @@ public static SingleInstancePostgresExtension singleInstance() { * Returns a {@link Extension} to create a Postgres cluster, shared amongst all test cases in this JVM. * The rule contributes Config switches to configure each test case to get its own database. */ - public static PreparedDbExtension preparedDatabase(DatabasePreparer preparer) - { + public static PreparedDbExtension preparedDatabase(DatabasePreparer preparer) { return new PreparedDbExtension(preparer); } diff --git a/src/main/java/io/zonky/test/db/postgres/junit5/PreparedDbExtension.java b/src/main/java/io/zonky/test/db/postgres/junit5/PreparedDbExtension.java index 81cf457f..66a5c9f6 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit5/PreparedDbExtension.java +++ b/src/main/java/io/zonky/test/db/postgres/junit5/PreparedDbExtension.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.ConnectionInfo; @@ -57,6 +60,7 @@ public void beforeAll(ExtensionContext extensionContext) throws Exception { perClass = true; } + @SuppressWarnings("PMD.NullAssignment") @Override public void afterAll(ExtensionContext extensionContext) { dataSource = null; @@ -74,6 +78,7 @@ public void beforeEach(ExtensionContext extensionContext) throws Exception { } } + @SuppressWarnings("PMD.NullAssignment") @Override public void afterEach(ExtensionContext extensionContext) { if (!perClass) { diff --git a/src/main/java/io/zonky/test/db/postgres/junit5/SingleInstancePostgresExtension.java b/src/main/java/io/zonky/test/db/postgres/junit5/SingleInstancePostgresExtension.java index 0b8cc27c..cfa48631 100644 --- a/src/main/java/io/zonky/test/db/postgres/junit5/SingleInstancePostgresExtension.java +++ b/src/main/java/io/zonky/test/db/postgres/junit5/SingleInstancePostgresExtension.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.EmbeddedPostgres; @@ -31,7 +34,7 @@ public class SingleInstancePostgresExtension implements AfterTestExecutionCallba private volatile Connection postgresConnection; private final List> builderCustomizers = new CopyOnWriteArrayList<>(); - SingleInstancePostgresExtension() { } + SingleInstancePostgresExtension() {} @Override public void beforeTestExecution(ExtensionContext extensionContext) throws Exception { @@ -45,6 +48,7 @@ private EmbeddedPostgres pg() throws IOException { return builder.start(); } + @SuppressWarnings("unused") public SingleInstancePostgresExtension customize(Consumer customizer) { if (epg != null) { throw new AssertionError("already started"); @@ -53,8 +57,7 @@ public SingleInstancePostgresExtension customize(Consumer builder.setConnectConfig("connectTimeout", "20")); @@ -35,7 +52,7 @@ public void test() throws SQLException { assertEquals("20", preparerDataSource.getProperty("connectTimeout")); } - private class CapturingDatabasePreparer implements DatabasePreparer { + private static class CapturingDatabasePreparer implements DatabasePreparer { private DataSource dataSource; diff --git a/src/test/java/io/zonky/test/db/postgres/junit/FlywayPreparerTest.java b/src/test/java/io/zonky/test/db/postgres/junit/FlywayPreparerTest.java index cebb9376..73776e8b 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/FlywayPreparerTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/FlywayPreparerTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,29 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; -import static org.junit.Assert.assertEquals; +import io.zonky.test.db.postgres.embedded.FlywayPreparer; +import org.junit.Rule; +import org.junit.Test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Collections; -import io.zonky.test.db.postgres.embedded.FlywayPreparer; -import org.junit.Rule; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class FlywayPreparerTest { @Rule public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(FlywayPreparer.fromConfiguration( Collections.singletonMap("flyway.locations", "db/testing"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/IsolationTest.java b/src/test/java/io/zonky/test/db/postgres/junit/IsolationTest.java index 7184d23a..898d1171 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/IsolationTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/IsolationTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; +import org.junit.Rule; +import org.junit.Test; + import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; -import org.junit.Rule; -import org.junit.Test; - -public class IsolationTest -{ +public class IsolationTest { @Rule public SingleInstancePostgresRule pg1 = EmbeddedPostgresRules.singleInstance(); @@ -29,8 +31,7 @@ public class IsolationTest public SingleInstancePostgresRule pg2 = EmbeddedPostgresRules.singleInstance(); @Test - public void testIsolation() throws Exception - { + public void testIsolation() throws Exception { try (Connection c = getConnection(pg1)) { makeTable(c); try (Connection c2 = getConnection(pg2)) { @@ -39,14 +40,14 @@ public void testIsolation() throws Exception } } - private void makeTable(Connection c) throws SQLException - { - Statement s = c.createStatement(); - s.execute("CREATE TABLE public.foo (a INTEGER)"); + @SuppressWarnings("SqlNoDataSourceInspection") + private void makeTable(Connection c) throws SQLException { + try (Statement s = c.createStatement()) { + s.execute("CREATE TABLE public.foo (a INTEGER)"); + } } - private Connection getConnection(SingleInstancePostgresRule epg) throws SQLException - { + private Connection getConnection(SingleInstancePostgresRule epg) throws SQLException { return epg.getEmbeddedPostgres().getPostgresDatabase().getConnection(); } } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathContextTest.java b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathContextTest.java index 647a514d..13318560 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathContextTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathContextTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -29,11 +32,12 @@ public class LiquibasePreparerClasspathContextTest { @Rule public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master-test.xml", new Contexts("test"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testEmptyTables() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo")) { rs.next(); assertEquals(0, rs.getInt(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathTest.java b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathTest.java index 07156b36..70b88b52 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerClasspathTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -28,11 +31,12 @@ public class LiquibasePreparerClasspathTest { @Rule public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master.xml")); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileContextTest.java b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileContextTest.java index f1b38523..52527616 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileContextTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileContextTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -30,11 +33,12 @@ public class LiquibasePreparerFileContextTest { @Rule public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(LiquibasePreparer.forFile(new File("src/test/resources/liqui/master-test.xml"), new Contexts("test"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testEmptyTables() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo")) { rs.next(); assertEquals(0, rs.getInt(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileTest.java b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileTest.java index 233bda84..7d89dc56 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/LiquibasePreparerFileTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -29,11 +32,12 @@ public class LiquibasePreparerFileTest { @Rule public PreparedDbRule db = EmbeddedPostgresRules.preparedDatabase(LiquibasePreparer.forFile(new File("src/test/resources/liqui/master.xml"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbCustomizerTest.java b/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbCustomizerTest.java index 41c0542c..24407ae0 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbCustomizerTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbCustomizerTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.DatabasePreparer; diff --git a/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbTest.java b/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbTest.java index 7b01c181..9f0eb58f 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/PreparedDbTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,18 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.zonky.test.db.postgres.junit; - -import static org.junit.Assert.assertEquals; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import javax.sql.DataSource; +package io.zonky.test.db.postgres.junit; import io.zonky.test.db.postgres.embedded.ConnectionInfo; import io.zonky.test.db.postgres.embedded.DatabaseConnectionPreparer; @@ -30,6 +22,11 @@ import org.junit.Rule; import org.junit.Test; +import javax.sql.DataSource; +import java.sql.*; + +import static org.junit.Assert.assertEquals; + public class PreparedDbTest { private final DatabasePreparer prepA = new SimplePreparer("a"); @@ -42,6 +39,7 @@ public class PreparedDbTest { @Rule public PreparedDbRule dbB1 = EmbeddedPostgresRules.preparedDatabase(prepB); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testDbs() throws Exception { try (Connection c = dbA1.getTestDatabase().getConnection(); @@ -49,8 +47,8 @@ public void testDbs() throws Exception { commonAssertion(stmt); } try (Connection c = dbA2.getTestDatabase().getConnection(); - PreparedStatement stmt = c.prepareStatement("SELECT count(1) FROM a")) { - ResultSet rs = stmt.executeQuery(); + PreparedStatement stmt = c.prepareStatement("SELECT count(1) FROM a"); + ResultSet rs = stmt.executeQuery()) { rs.next(); assertEquals(0, rs.getInt(1)); } @@ -60,11 +58,13 @@ public void testDbs() throws Exception { } } + @SuppressWarnings("SqlNoDataSourceInspection") private void commonAssertion(final Statement stmt) throws SQLException { stmt.execute("INSERT INTO a VALUES(1)"); - ResultSet rs = stmt.executeQuery("SELECT COUNT(1) FROM a"); - rs.next(); - assertEquals(1, rs.getInt(1)); + try (ResultSet rs = stmt.executeQuery("SELECT COUNT(1) FROM a")) { + rs.next(); + assertEquals(1, rs.getInt(1)); + } } @Test @@ -80,7 +80,7 @@ public void testEquivalentAccess() throws SQLException { @Test public void testDbUri() throws Exception { try (Connection c = DriverManager.getConnection(dbA1.getDbProvider().createDatabase()); - Statement stmt = c.createStatement()) { + Statement stmt = c.createStatement()) { commonAssertion(stmt); } } diff --git a/src/test/java/io/zonky/test/db/postgres/junit/SingleInstanceRuleTest.java b/src/test/java/io/zonky/test/db/postgres/junit/SingleInstanceRuleTest.java index d8ec7f21..cd5a79fe 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit/SingleInstanceRuleTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit/SingleInstanceRuleTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,29 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; -import org.junit.Rule; -import org.junit.Test; +import static org.junit.Assert.*; -public class SingleInstanceRuleTest -{ +public class SingleInstanceRuleTest { @Rule public SingleInstancePostgresRule epg = EmbeddedPostgresRules.singleInstance(); + @SuppressWarnings("SqlNoDataSourceInspection") @Test public void testRule() throws Exception { - try (Connection c = epg.getEmbeddedPostgres().getPostgresDatabase().getConnection()) { - Statement s = c.createStatement(); - ResultSet rs = s.executeQuery("SELECT 1"); + try (Connection c = epg.getEmbeddedPostgres().getPostgresDatabase().getConnection(); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT 1")) { assertTrue(rs.next()); assertEquals(1, rs.getInt(1)); assertFalse(rs.next()); diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/ConnectConfigTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/ConnectConfigTest.java index 62e7865d..7df570c6 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/ConnectConfigTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/ConnectConfigTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2025 Tomas Vanek + * + * 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. + */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.ConnectionInfo; @@ -12,16 +28,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class ConnectConfigTest { +class ConnectConfigTest { private final CapturingDatabasePreparer preparer = new CapturingDatabasePreparer(); + @SuppressWarnings({"PMD.AvoidDuplicateLiterals", "JUnitMalformedDeclaration"}) @RegisterExtension - public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(preparer) + PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(preparer) .customize(builder -> builder.setConnectConfig("connectTimeout", "20")); @Test - public void test() throws SQLException { + void test() throws SQLException { ConnectionInfo connectionInfo = db.getConnectionInfo(); Map properties = connectionInfo.getProperties(); @@ -35,7 +52,7 @@ public void test() throws SQLException { assertEquals("20", preparerDataSource.getProperty("connectTimeout")); } - private class CapturingDatabasePreparer implements DatabasePreparer { + private static class CapturingDatabasePreparer implements DatabasePreparer { private DataSource dataSource; diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/DatabaseLifecycleTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/DatabaseLifecycleTest.java index a37eff69..48fb1bed 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/DatabaseLifecycleTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/DatabaseLifecycleTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2025 Tomas Vanek + * + * 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. + */ + package io.zonky.test.db.postgres.junit5; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; @@ -15,52 +31,48 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @TestMethodOrder(OrderAnnotation.class) -public class DatabaseLifecycleTest { +class DatabaseLifecycleTest { @RegisterExtension - public static PreparedDbExtension staticExtension = EmbeddedPostgresExtension.preparedDatabase(ds -> {}); + static PreparedDbExtension staticExtension = EmbeddedPostgresExtension.preparedDatabase(ds -> {}); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension instanceExtension = EmbeddedPostgresExtension.preparedDatabase(ds -> {}); + PreparedDbExtension instanceExtension = EmbeddedPostgresExtension.preparedDatabase(ds -> {}); @Test @Order(1) - public void testCreate1() throws Exception - { + void testCreate1() throws Exception { createTable(staticExtension, "table1"); createTable(instanceExtension, "table2"); } @Test @Order(2) - public void testCreate2() throws Exception - { + void testCreate2() throws Exception { assertTrue(existsTable(staticExtension, "table1")); assertFalse(existsTable(instanceExtension, "table2")); } @Test @Order(3) - public void testCreate3() throws Exception - { + void testCreate3() throws Exception { assertTrue(existsTable(staticExtension, "table1")); assertFalse(existsTable(instanceExtension, "table2")); } - private void createTable(PreparedDbExtension extension, String table) throws SQLException - { + private void createTable(PreparedDbExtension extension, String table) throws SQLException { try (Connection connection = extension.getTestDatabase().getConnection(); - Statement statement = connection.createStatement()) { + Statement statement = connection.createStatement()) { statement.execute(String.format("CREATE TABLE public.%s (a INTEGER)", table)); } } - private boolean existsTable(PreparedDbExtension extension, String table) throws SQLException - { + private boolean existsTable(PreparedDbExtension extension, String table) throws SQLException { + String query = String.format("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '%s')", table); try (Connection connection = extension.getTestDatabase().getConnection(); - Statement statement = connection.createStatement()) { - String query = String.format("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '%s')", table); - ResultSet resultSet = statement.executeQuery(query); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(query)) { resultSet.next(); return resultSet.getBoolean(1); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/FlywayPreparerTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/FlywayPreparerTest.java index c5aa84b1..a02080f0 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/FlywayPreparerTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/FlywayPreparerTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,27 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; -import static org.junit.jupiter.api.Assertions.assertEquals; +import io.zonky.test.db.postgres.embedded.FlywayPreparer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; -import io.zonky.test.db.postgres.embedded.FlywayPreparer; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class FlywayPreparerTest { +class FlywayPreparerTest { + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(FlywayPreparer.forClasspathLocation("db/testing")); + PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(FlywayPreparer.forClasspathLocation("db/testing")); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testTablesMade() throws Exception { + void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/IsolationTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/IsolationTest.java index afe4d606..a5eb765f 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/IsolationTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/IsolationTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,26 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -public class IsolationTest -{ +class IsolationTest { @RegisterExtension - public SingleInstancePostgresExtension pg1 = EmbeddedPostgresExtension.singleInstance(); + SingleInstancePostgresExtension pg1 = EmbeddedPostgresExtension.singleInstance(); @RegisterExtension - public SingleInstancePostgresExtension pg2 = EmbeddedPostgresExtension.singleInstance(); + SingleInstancePostgresExtension pg2 = EmbeddedPostgresExtension.singleInstance(); @Test - public void testIsolation() throws Exception - { + void testIsolation() throws Exception { try (Connection c = getConnection(pg1)) { makeTable(c); try (Connection c2 = getConnection(pg2)) { @@ -39,14 +40,14 @@ public void testIsolation() throws Exception } } - private void makeTable(Connection c) throws SQLException - { - Statement s = c.createStatement(); - s.execute("CREATE TABLE public.foo (a INTEGER)"); + @SuppressWarnings("SqlNoDataSourceInspection") + private void makeTable(Connection c) throws SQLException { + try (Statement s = c.createStatement()) { + s.execute("CREATE TABLE public.foo (a INTEGER)"); + } } - private Connection getConnection(SingleInstancePostgresExtension epg) throws SQLException - { + private Connection getConnection(SingleInstancePostgresExtension epg) throws SQLException { return epg.getEmbeddedPostgres().getPostgresDatabase().getConnection(); } } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathContextTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathContextTest.java index 436b64e8..56102660 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathContextTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathContextTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -24,16 +27,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class LiquibasePreparerClasspathContextTest { +class LiquibasePreparerClasspathContextTest { + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master-test.xml", new Contexts("test"))); + PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master-test.xml", new Contexts("test"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testEmptyTables() throws Exception { + void testEmptyTables() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo")) { rs.next(); assertEquals(0, rs.getInt(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathTest.java index 1319ee81..f51dfb77 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerClasspathTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -23,16 +26,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class LiquibasePreparerClasspathTest { +class LiquibasePreparerClasspathTest { + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master.xml")); + PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forClasspathLocation("liqui/master.xml")); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testTablesMade() throws Exception { + void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileContextTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileContextTest.java index 837792bd..c03f07d6 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileContextTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileContextTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -25,16 +28,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class LiquibasePreparerFileContextTest { +class LiquibasePreparerFileContextTest { + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forFile(new File("src/test/resources/liqui/master-test.xml"), new Contexts("test"))); + PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forFile(new File("src/test/resources/liqui/master-test.xml"), new Contexts("test"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testEmptyTables() throws Exception { + void testEmptyTables() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT COUNT(*) FROM foo")) { rs.next(); assertEquals(0, rs.getInt(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileTest.java index 8c0c5378..1440a1e4 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/LiquibasePreparerFileTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.LiquibasePreparer; @@ -24,16 +27,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class LiquibasePreparerFileTest { +class LiquibasePreparerFileTest { + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension public PreparedDbExtension db = EmbeddedPostgresExtension.preparedDatabase(LiquibasePreparer.forFile(new File("src/test/resources/liqui/master.xml"))); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testTablesMade() throws Exception { + void testTablesMade() throws Exception { try (Connection c = db.getTestDatabase().getConnection(); - Statement s = c.createStatement()) { - ResultSet rs = s.executeQuery("SELECT * FROM foo"); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT * FROM foo")) { rs.next(); assertEquals("bar", rs.getString(1)); } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbCustomizerTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbCustomizerTest.java index a5b9bdfa..1aa01927 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbCustomizerTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbCustomizerTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.DatabasePreparer; @@ -22,23 +25,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -public class PreparedDbCustomizerTest { +class PreparedDbCustomizerTest { private static final DatabasePreparer EMPTY_PREPARER = ds -> {}; + @SuppressWarnings({"JUnitMalformedDeclaration", "PMD.AvoidDuplicateLiterals"}) @RegisterExtension - public PreparedDbExtension dbA1 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER); + PreparedDbExtension dbA1 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbA2 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> {}); + PreparedDbExtension dbA2 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> {}); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbA3 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(10))); + PreparedDbExtension dbA3 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(10))); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbB1 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(11))); + PreparedDbExtension dbB1 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(11))); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbB2 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(11))); + PreparedDbExtension dbB2 = EmbeddedPostgresExtension.preparedDatabase(EMPTY_PREPARER).customize(builder -> builder.setPGStartupWait(Duration.ofSeconds(11))); @Test - public void testCustomizers() { + void testCustomizers() { int dbA1Port = dbA1.getConnectionInfo().getPort(); int dbA2Port = dbA2.getConnectionInfo().getPort(); int dbA3Port = dbA3.getConnectionInfo().getPort(); diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbTest.java index c4a75409..6174f793 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/PreparedDbTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,18 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.zonky.test.db.postgres.junit5; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import javax.sql.DataSource; +package io.zonky.test.db.postgres.junit5; import io.zonky.test.db.postgres.embedded.ConnectionInfo; import io.zonky.test.db.postgres.embedded.DatabaseConnectionPreparer; @@ -30,27 +22,36 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -public class PreparedDbTest { +import javax.sql.DataSource; +import java.sql.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PreparedDbTest { private final DatabasePreparer prepA = new SimplePreparer("a"); private final DatabasePreparer prepB = new SimplePreparer("b"); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbA1 = EmbeddedPostgresExtension.preparedDatabase(prepA); + PreparedDbExtension dbA1 = EmbeddedPostgresExtension.preparedDatabase(prepA); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbA2 = EmbeddedPostgresExtension.preparedDatabase(prepA); + PreparedDbExtension dbA2 = EmbeddedPostgresExtension.preparedDatabase(prepA); + @SuppressWarnings("JUnitMalformedDeclaration") @RegisterExtension - public PreparedDbExtension dbB1 = EmbeddedPostgresExtension.preparedDatabase(prepB); + PreparedDbExtension dbB1 = EmbeddedPostgresExtension.preparedDatabase(prepB); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testDbs() throws Exception { + void testDbs() throws Exception { try (Connection c = dbA1.getTestDatabase().getConnection(); Statement stmt = c.createStatement()) { commonAssertion(stmt); } try (Connection c = dbA2.getTestDatabase().getConnection(); - PreparedStatement stmt = c.prepareStatement("SELECT count(1) FROM a")) { - ResultSet rs = stmt.executeQuery(); + PreparedStatement stmt = c.prepareStatement("SELECT count(1) FROM a"); + ResultSet rs = stmt.executeQuery()) { rs.next(); assertEquals(0, rs.getInt(1)); } @@ -60,15 +61,17 @@ public void testDbs() throws Exception { } } + @SuppressWarnings("SqlNoDataSourceInspection") private void commonAssertion(final Statement stmt) throws SQLException { stmt.execute("INSERT INTO a VALUES(1)"); - ResultSet rs = stmt.executeQuery("SELECT COUNT(1) FROM a"); - rs.next(); - assertEquals(1, rs.getInt(1)); + try (ResultSet rs = stmt.executeQuery("SELECT COUNT(1) FROM a")) { + rs.next(); + assertEquals(1, rs.getInt(1)); + } } @Test - public void testEquivalentAccess() throws SQLException { + void testEquivalentAccess() throws SQLException { ConnectionInfo dbInfo = dbA1.getConnectionInfo(); DataSource dataSource = dbA1.getTestDatabase(); try (Connection c = dataSource.getConnection(); Statement stmt = c.createStatement()) { @@ -78,9 +81,9 @@ public void testEquivalentAccess() throws SQLException { } @Test - public void testDbUri() throws Exception { + void testDbUri() throws Exception { try (Connection c = DriverManager.getConnection(dbA1.getDbProvider().createDatabase()); - Statement stmt = c.createStatement()) { + Statement stmt = c.createStatement()) { commonAssertion(stmt); } } diff --git a/src/test/java/io/zonky/test/db/postgres/junit5/SingleInstanceRuleTest.java b/src/test/java/io/zonky/test/db/postgres/junit5/SingleInstanceRuleTest.java index 1df4c0f7..6e297d6c 100644 --- a/src/test/java/io/zonky/test/db/postgres/junit5/SingleInstanceRuleTest.java +++ b/src/test/java/io/zonky/test/db/postgres/junit5/SingleInstanceRuleTest.java @@ -1,9 +1,11 @@ /* + * Copyright 2025 Tomas Vanek + * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -11,29 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package io.zonky.test.db.postgres.junit5; -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.extension.RegisterExtension; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; +import static org.junit.jupiter.api.Assertions.*; -public class SingleInstanceRuleTest -{ +class SingleInstanceRuleTest { @RegisterExtension - public SingleInstancePostgresExtension epg = EmbeddedPostgresExtension.singleInstance(); + SingleInstancePostgresExtension epg = EmbeddedPostgresExtension.singleInstance(); + @SuppressWarnings("SqlNoDataSourceInspection") @Test - public void testRule() throws Exception { - try (Connection c = epg.getEmbeddedPostgres().getPostgresDatabase().getConnection()) { - Statement s = c.createStatement(); - ResultSet rs = s.executeQuery("SELECT 1"); + void testRule() throws Exception { + try (Connection c = epg.getEmbeddedPostgres().getPostgresDatabase().getConnection(); + Statement s = c.createStatement(); + ResultSet rs = s.executeQuery("SELECT 1")) { assertTrue(rs.next()); assertEquals(1, rs.getInt(1)); assertFalse(rs.next()); diff --git a/src/test/resources/liqui/master-test.xml b/src/test/resources/liqui/master-test.xml index 3670a29b..7871dd78 100644 --- a/src/test/resources/liqui/master-test.xml +++ b/src/test/resources/liqui/master-test.xml @@ -15,7 +15,7 @@ + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> @@ -26,6 +26,7 @@ Fill `foo` table + INSERT INTO foo VALUES('bar'); diff --git a/src/test/resources/liqui/master.xml b/src/test/resources/liqui/master.xml index d82881b6..cc34a074 100644 --- a/src/test/resources/liqui/master.xml +++ b/src/test/resources/liqui/master.xml @@ -15,7 +15,7 @@ + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> @@ -23,6 +23,7 @@ Create table `foo` + CREATE TABLE foo (test VARCHAR); @@ -30,6 +31,7 @@ Fill `foo` table + INSERT INTO foo VALUES('bar'); diff --git a/src/test/resources/simplelogger.properties b/src/test/resources/simplelogger.properties index 6dfc7aa3..e4595c26 100644 --- a/src/test/resources/simplelogger.properties +++ b/src/test/resources/simplelogger.properties @@ -1 +1 @@ -org.slf4j.simpleLogger.showDateTime=true \ No newline at end of file +org.slf4j.simpleLogger.showDateTime = true \ No newline at end of file