diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..0068402
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+
+ - package-ecosystem: "gradle"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..3a24f7f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,52 @@
+name: CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Java 25
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 25
+
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v4
+
+ - name: Compile
+ run: ./gradlew clean assemble
+
+ - name: Test
+ run: ./gradlew -PtestMode=slow test
+
+ - name: Checkstyle
+ if: success() || failure()
+ run: ./gradlew checkstyleMain
+
+ - name: Jacoco Coverage Verification
+ if: success() || failure()
+ run: ./gradlew jacocoTestCoverageVerification
+
+ - name: Upload test results
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results
+ path: build/reports/tests/xml/
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: jars
+ path: build/libs/*.jar
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 9bc621c..51b6586 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,22 +1,9 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-# ******** NOTE ********
-
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
- # The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '45 16 * * 2'
@@ -30,39 +17,24 @@ jobs:
fail-fast: false
matrix:
language: [ 'java' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more...
- # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
+
+ - name: Set up Java 25
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 25
- # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v1
-
- # ℹ️ Command-line programs to run using the OS shell.
- # 📚 https://git.io/JvXDl
-
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
- #- run: |
- # make bootstrap
- # make release
+ - name: Build
+ run: ./gradlew clean assemble
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v3
diff --git a/build.gradle b/build.gradle
index 38ca0ab..fa4c846 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,38 +1,123 @@
-apply from: 'build.shared'
-apply plugin: 'checkstyle'
-apply plugin: 'jacoco'
+plugins {
+ id 'java'
+ id 'checkstyle'
+ id 'jacoco'
+ id 'maven-publish'
+ id 'signing'
+}
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(25)
+ }
+}
-plugins.withType(JavaPlugin) {
- checkstyle.sourceSets = [sourceSets.main]
+repositories {
+ mavenCentral()
}
+dependencies {
+ testImplementation 'org.junit.jupiter:junit-jupiter:6.0.3'
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher:6.0.3'
+ implementation "org.threadly:threadly:$threadlyVersion"
+}
+
+compileJava {
+ options.compilerArgs << '-Xlint:all' << '-Xlint:-deprecation' << '-Xlint:-this-escape' << '-Werror'
+}
+
+compileTestJava {
+ options.compilerArgs << '-Xlint:all'
+}
+
+checkstyle {
+ sourceSets = [sourceSets.main]
+}
+
+def testMode = project.findProperty('testMode') ?: 'default'
+
test {
- maxParallelForks = Math.min(8, Math.max(1, (int)(Runtime.getRuntime().availableProcessors() / 4)))
+ useJUnitPlatform()
+
+ switch (testMode) {
+ case 'slow':
+ maxParallelForks = 1
+ systemProperty 'systemSpeed', 'slow'
+ break
+ case 'stress':
+ systemProperty 'systemSpeed', 'slow'
+ systemProperty 'testProfile', 'stress'
+ maxParallelForks = Math.min(8, Math.max(1, (int)(Runtime.getRuntime().availableProcessors() / 2)))
+ break
+ default:
+ maxParallelForks = Math.min(8, Math.max(1, (int)(Runtime.getRuntime().availableProcessors() / 4)))
+ break
+ }
+
+ reports {
+ junitXml.outputLocation = layout.buildDirectory.dir('reports/tests/xml')
+ html.outputLocation = layout.buildDirectory.dir('reports/tests/html')
+ }
+ binaryResultsDirectory = layout.buildDirectory.dir('reports/tests/bin')
+
jacoco {
- excludes = ['**/package-info**','**/*Test']
- destinationFile = file("$buildDir/reports/jacoco/test.exec")
+ excludes = ['**/package-info**', '**/*Test']
+ destinationFile = layout.buildDirectory.file('reports/jacoco/test.exec').get().asFile
}
}
-test.dependsOn("jar")
+test.dependsOn('jar')
+
+jar {
+ manifest {
+ attributes(
+ 'Implementation-Title': 'Threadly Test Utilities',
+ 'Implementation-Version': archiveVersion.get()
+ )
+ }
+}
+
+javadoc {
+ source = sourceSets.main.allJava
+ excludes = ['**/ThreadlyInternalAccessor**', '**/ArgumentVerifier**']
+ options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PUBLIC
+}
+
+tasks.register('javadocJar', Jar) {
+ dependsOn javadoc
+ archiveClassifier.set('javadoc')
+ from javadoc.destinationDir
+}
+
+tasks.register('sourcesJar', Jar) {
+ from sourceSets.main.allSource
+ archiveClassifier.set('sources')
+}
+
+tasks.register('copyLibs', Copy) {
+ into layout.buildDirectory.dir('dependencies')
+ from configurations.runtimeClasspath
+}
+
+build.finalizedBy('copyLibs')
jacocoTestReport {
reports {
csv.required = false
xml.required = true
- xml.destination = file("$buildDir/reports/jacoco/jacoco.xml")
+ xml.outputLocation = layout.buildDirectory.file('reports/jacoco/jacoco.xml')
html.required = true
- html.destination = file("$buildDir/reports/jacoco/html")
+ html.outputLocation = layout.buildDirectory.dir('reports/jacoco/html')
}
doLast {
println "Test results available at:"
- println "html - $buildDir/reports/tests/html/index.html"
+ println "html - ${layout.buildDirectory.dir('reports/tests/html').get().asFile}/index.html"
println "Test coverage reports available at:"
- println "html - $buildDir/reports/jacoco/html/index.html"
+ println "html - ${layout.buildDirectory.dir('reports/jacoco/html').get().asFile}/index.html"
}
}
-test.finalizedBy("jacocoTestReport")
+test.finalizedBy('jacocoTestReport')
jacocoTestCoverageVerification {
violationRules {
@@ -63,4 +148,68 @@ jacocoTestCoverageVerification {
}
}
-jacocoTestReport.finalizedBy("jacocoTestCoverageVerification")
+jacocoTestReport.finalizedBy('jacocoTestCoverageVerification')
+
+publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ from components.java
+
+ artifact(tasks.named('sourcesJar'))
+ artifact(tasks.named('javadocJar'))
+
+ pom {
+ name = 'Threadly Test Utilities'
+ description = 'A library of tools to assist with testing concurrent java applications.'
+ url = 'https://threadly.org/'
+
+ scm {
+ url = 'scm:git@github.com:threadly/threadly-test.git'
+ connection = 'scm:git@github.com:threadly/threadly-test.git'
+ developerConnection = 'scm:git@github.com:threadly/threadly-test.git'
+ }
+
+ issueManagement {
+ system = 'GitHub'
+ url = 'https://github.com/threadly/threadly-test/issues'
+ }
+
+ licenses {
+ license {
+ name = 'Mozilla Public License Version 2.0'
+ url = 'https://www.mozilla.org/MPL/2.0/'
+ distribution = 'repo'
+ }
+ }
+
+ developers {
+ developer {
+ id = 'jent'
+ name = 'Mike Jensen'
+ email = 'jent@threadly.org'
+ }
+ }
+ }
+ }
+ }
+ repositories {
+ maven {
+ def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
+ def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots'
+ url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
+ credentials {
+ username = findProperty('sonatypeUsername') ?: ''
+ password = findProperty('sonatypePassword') ?: ''
+ }
+ }
+ }
+}
+
+tasks.withType(GenerateMavenPom).configureEach {
+ destination = layout.buildDirectory.file('generated-pom.xml').get().asFile
+}
+
+signing {
+ required = { !version.toString().contains('SNAPSHOT') && gradle.taskGraph.hasTask('publish') }
+ sign publishing.publications.mavenJava
+}
diff --git a/build.shared b/build.shared
deleted file mode 100644
index b9b2b6d..0000000
--- a/build.shared
+++ /dev/null
@@ -1,71 +0,0 @@
-apply plugin: 'java'
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- testImplementation (
- "junit:junit:4.13.2",
- )
-
- implementation (
- "org.threadly:threadly:$threadlyVersion"
- )
-}
-
-compileJava {
- options.compilerArgs << "-Xlint:all" << "-Xlint:-deprecation" << "-Werror"
-
- if (JavaVersion.current().isJava8()) {
- options.compilerArgs << "-XDenableSunApiLintControl" << "-Xlint:-sunapi"
- }
-}
-
-compileTestJava {
- options.compilerArgs << "-Xlint:all"
-}
-
-test {
- getReports().getJunitXml().setDestination(file("$buildDir/reports/tests/xml"))
- getReports().getHtml().setDestination(file("$buildDir/reports/tests/html"))
- setBinaryResultsDirectory(file("$buildDir/reports/tests/bin"))
-}
-
-jar {
- manifest {
- attributes (
- 'Implementation-Title': 'Threadly Test Utilities',
- 'Implementation-Version': archiveVersion
- )
- }
-}
-
-javadoc {
- source = sourceSets.main.allJava
- excludes = ['**/ThreadlyInternalAccessor**', '**/ArgumentVerifier**']
- options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PUBLIC
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier = 'javadoc'
- from 'build/docs/javadoc'
-}
-
-task sourcesJar(type: Jar) {
- from sourceSets.main.allSource
- classifier = 'sources'
-}
-
-task copyLibs(type: Copy) {
- into "$buildDir/dependencies/"
- from configurations.runtimeClasspath
-}
-
-build.finalizedBy("copyLibs")
-
-artifacts {
- //archives jar // already specified by default
- archives javadocJar
- archives sourcesJar
-}
diff --git a/build.slow b/build.slow
deleted file mode 100644
index 8f3e930..0000000
--- a/build.slow
+++ /dev/null
@@ -1,7 +0,0 @@
-apply from: 'build.gradle'
-apply plugin: 'jacoco'
-
-test {
- maxParallelForks = 1
- systemProperty 'systemSpeed', 'slow'
-}
diff --git a/build.stress b/build.stress
deleted file mode 100644
index 764edc1..0000000
--- a/build.stress
+++ /dev/null
@@ -1,8 +0,0 @@
-apply from: 'build.gradle'
-apply plugin: 'jacoco'
-
-test {
- systemProperty 'systemSpeed', 'slow'
- systemProperty 'testProfile', 'stress'
- maxParallelForks = Math.min(8, Math.max(1, (int)(Runtime.getRuntime().availableProcessors() / 2)))
-}
diff --git a/build.upload b/build.upload
deleted file mode 100644
index e7df192..0000000
--- a/build.upload
+++ /dev/null
@@ -1,122 +0,0 @@
-apply from: 'build.shared'
-apply plugin: 'maven-publish'
-apply plugin: 'signing'
-
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
-
-test {
- maxParallelForks = Math.max(1, (int)(Runtime.getRuntime().availableProcessors() / 2))
-}
-
-test.dependsOn("jar")
-
-def findJVM() {
- String[] java8Paths = new String[5]
- java8Paths[0] = "/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/"
- java8Paths[1] = "/usr/lib/jvm/java-8-openjdk/jre/lib/"
- java8Paths[2] = "/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/"
- java8Paths[3] = "/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/"
- java8Paths[4] = "/usr/lib/jvm/java-8-sun/jre/lib/"
- for (String path : java8Paths) {
- if (new java.io.File(path).exists()) {
- return path
- }
- }
- return null
-}
-
-compileJava {
- def jvmPath = findJVM()
- if (jvmPath == null) {
- println 'Unable to find java 8 rt.jar, will cause failure so exiting now'
- println ''
- System.exit(1)
- }
- println 'Using java 8: ' + jvmPath
- options.bootstrapClasspath = fileTree(include: ['*.jar'], dir: jvmPath)
-}
-
-compileTestJava {
- options.compilerArgs << "-Xlint:all" << "-Xlint:-deprecation" << "-Werror"
-
- options.bootstrapClasspath = fileTree(include: ['*.jar'], dir: findJVM())
-}
-
-signing {
- sign configurations.archives
- if (! version.contains('SNAPSHOT')) {
- sign publishing.publications
- }
-}
-
-publishing {
- publications {
- mavenJava(MavenPublication) {
- pom {
- name = 'Threadly'
- description = 'A library of tools to assist with safe concurrent java development.'
- url = 'http://threadly.org/'
-
- scm {
- url = 'scm:git@github.com:threadly/threadly.git'
- connection = 'scm:git@github.com:threadly/threadly.git'
- developerConnection = 'scm:git@github.com:threadly/threadly.git'
- }
-
- issueManagement {
- system = 'GitHub'
- url = 'https://github.com/threadly/threadly/issues'
- }
-
- licenses {
- license {
- name = 'Mozilla Public License Version 2.0'
- url = 'https://www.mozilla.org/MPL/2.0/'
- distribution = 'repo'
- }
- }
-
- developers {
- developer {
- id = 'jent'
- name = 'Mike Jensen'
- email = 'jent@threadly.org'
- }
- }
- }
-
- from components.java
-
- artifact(sourcesJar) {
- classifier = 'sources'
- }
- artifact(javadocJar) {
- classifier = 'javadoc'
- }
- }
- }
- repositories {
- maven {
- def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
- def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
- url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
- credentials {
- username sonatypeUsername
- password sonatypePassword
- }
- }
- }
-}
-
-model {
- tasks.generatePomFileForMavenJavaPublication {
- destination = file("$buildDir/generated-pom.xml")
- }
- tasks.publishMavenJavaPublicationToMavenLocal {
- dependsOn project.tasks.signArchives
- }
- tasks.publishMavenJavaPublicationToMavenRepository {
- dependsOn project.tasks.signArchives
- }
-}
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 4a5e0dd..7f97afb 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -16,8 +16,7 @@
-
-
+
diff --git a/gradle.properties b/gradle.properties
index fb5053c..ac5fe3e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,5 +1,5 @@
group = org.threadly
-version = 1.1-SNAPSHOT
+version = 2.0-SNAPSHOT
org.gradle.parallel = false
threadlyVersion = 6.0
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7454180..61285a6 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2e6e589..37f78a6 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 1b6c787..adff685 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright © 2015-2021 the original authors.
+# 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.
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# 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/.
@@ -80,13 +82,11 @@ do
esac
done
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-APP_NAME="Gradle"
+# This is normally unused
+# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# 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
@@ -114,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -133,22 +132,29 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ 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
@@ -165,7 +171,6 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -193,18 +198,27 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# 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" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
+ -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.
diff --git a/gradlew.bat b/gradlew.bat
index ac1b06f..e509b2d 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,8 +13,10 @@
@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
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +27,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+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
@@ -56,32 +59,33 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+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
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+"%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%"=="0" goto mainEnd
+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!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+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
diff --git a/pipeline.yml b/pipeline.yml
deleted file mode 100644
index b63e5f4..0000000
--- a/pipeline.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-steps:
- - command: "./gradlew clean assemble"
- label: "compile"
- artifact_paths: "build/libs/*.jar"
- timeout: 10
-
- - wait
-
- - command: "./gradlew -b build.slow test"
- label: "unit tests"
- artifact_paths: "build/reports/tests/xml/*.xml"
- timeout: 20
-
- - wait: ~
- continue_on_failure: true
-
- - plugins:
- junit-annotate#v1.2.0:
- artifacts: build/reports/tests/xml/*.xml
-
- - command: "./gradlew checkstyleMain"
- label: "checkstyle"
- timeout: 10
-
- - command: "./gradlew jacocoTestCoverageVerification"
- label: "jacoco"
- timeout: 10
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..a55e95b
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'threadly-test'
diff --git a/src/test/java/org/threadly/Repeat.java b/src/test/java/org/threadly/Repeat.java
deleted file mode 100644
index e5d8ded..0000000
--- a/src/test/java/org/threadly/Repeat.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.threadly;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.METHOD;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@SuppressWarnings("javadoc")
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ METHOD, ANNOTATION_TYPE })
-public @interface Repeat {
- public int value() default 1;
-}
diff --git a/src/test/java/org/threadly/RepeatRule.java b/src/test/java/org/threadly/RepeatRule.java
deleted file mode 100644
index 2acea8a..0000000
--- a/src/test/java/org/threadly/RepeatRule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.threadly;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-@SuppressWarnings("javadoc")
-public class RepeatRule implements TestRule {
- @Override
- public Statement apply(Statement statement, Description description) {
- Statement result = statement;
- Repeat repeat = description.getAnnotation(Repeat.class);
- if (repeat != null) {
- int times = repeat.value();
- result = new RepeatStatement(statement, times);
- }
- return result;
- }
-
- private static class RepeatStatement extends Statement {
- private final Statement statement;
- private final int repeat;
-
- public RepeatStatement(Statement statement, int repeat) {
- this.statement = statement;
- this.repeat = repeat;
- }
-
- @Override
- public void evaluate() throws Throwable {
- for (int i = 0; i < repeat; i++) {
- statement.evaluate();
- }
- }
- }
-}
diff --git a/src/test/java/org/threadly/ThreadlyTester.java b/src/test/java/org/threadly/ThreadlyTester.java
index 51e388a..e5cdc4a 100644
--- a/src/test/java/org/threadly/ThreadlyTester.java
+++ b/src/test/java/org/threadly/ThreadlyTester.java
@@ -2,7 +2,6 @@
import java.lang.Thread.UncaughtExceptionHandler;
-import org.junit.Rule;
import org.threadly.util.ExceptionHandler;
import org.threadly.util.ExceptionUtils;
import org.threadly.util.StringUtils;
@@ -131,9 +130,6 @@ public static void setIgnoreExceptionHandler() {
ExceptionUtils.setDefaultExceptionHandler(ieh);
}
- @Rule
- public RepeatRule repeatRule = new RepeatRule();
-
private static class IgnoreExceptionHandler implements UncaughtExceptionHandler,
ExceptionHandler {
@Override
diff --git a/src/test/java/org/threadly/test/concurrent/AsyncVerifierTest.java b/src/test/java/org/threadly/test/concurrent/AsyncVerifierTest.java
index be126a6..5ac4aa9 100644
--- a/src/test/java/org/threadly/test/concurrent/AsyncVerifierTest.java
+++ b/src/test/java/org/threadly/test/concurrent/AsyncVerifierTest.java
@@ -1,56 +1,56 @@
package org.threadly.test.concurrent;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.TimeoutException;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.threadly.ThreadlyTester;
import org.threadly.util.ExceptionUtils;
import org.threadly.util.StringUtils;
@SuppressWarnings("javadoc")
public class AsyncVerifierTest extends ThreadlyTester {
- @BeforeClass
+ @BeforeAll
public static void setupClass() {
setIgnoreExceptionHandler();
}
-
- @AfterClass
+
+ @AfterAll
public static void cleanupClass() {
Thread.setDefaultUncaughtExceptionHandler(null);
}
-
+
private static final int ASYNC_WAIT_AMOUNT = 2;
-
+
private AsyncVerifier verifier;
-
- @Before
+
+ @BeforeEach
public void setup() {
verifier = new AsyncVerifier();
}
-
- @After
+
+ @AfterEach
public void cleanup() {
verifier = null;
}
-
- @Test (expected = TimeoutException.class)
- public void waitForTestTimeout() throws InterruptedException, TimeoutException {
- verifier.waitForTest(1);
+
+ @Test
+ public void waitForTestTimeout() {
+ assertThrows(TimeoutException.class, () -> verifier.waitForTest(1));
}
-
+
@Test
public void signalCompleteBeforeWaitTest() throws InterruptedException, TimeoutException {
verifier.signalComplete();
-
+
verifier.waitForTest(1); // no exception should throw as no blocking is needed
}
-
+
@Test
public void signalCompleteAnotherThreadTest() {
TestRunnable waitRunnable = new TestRunnable() {
@@ -64,53 +64,53 @@ public void handleRunFinish() {
}
};
new Thread(waitRunnable).start();
-
+
// should unblock thread
verifier.signalComplete();
-
+
waitRunnable.blockTillFinished(); // should return quickly
}
-
+
@Test
public void assertTrueTest() {
verifier.assertTrue(true);
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertTrueFail() {
- verifier.assertTrue(false);
+ assertThrows(RuntimeException.class, () -> verifier.assertTrue(false));
}
-
+
@Test
public void assertFalseTest() {
verifier.assertFalse(false);
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertFalseFail() {
- verifier.assertFalse(true);
+ assertThrows(RuntimeException.class, () -> verifier.assertFalse(true));
}
-
+
@Test
public void assertNullTest() {
verifier.assertNull(null);
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertNullFail() {
- verifier.assertNull(new Object());
+ assertThrows(RuntimeException.class, () -> verifier.assertNull(new Object()));
}
-
+
@Test
public void assertNotNullTest() {
verifier.assertNotNull(new Object());
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertNotNullFail() {
- verifier.assertNotNull(null);
+ assertThrows(RuntimeException.class, () -> verifier.assertNotNull(null));
}
-
+
@Test
public void assertEqualsTest() {
Object o = new Object();
@@ -120,22 +120,22 @@ public void assertEqualsTest() {
verifier.assertEquals(1L, 1L);
verifier.assertEquals(1.1, 1.1);
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertEqualsObjectFail() {
- verifier.assertEquals(null, new Object());
+ assertThrows(RuntimeException.class, () -> verifier.assertEquals(null, new Object()));
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void assertEqualsNumberFail() {
- verifier.assertEquals(1, 10.0);
+ assertThrows(RuntimeException.class, () -> verifier.assertEquals(1, 10.0));
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void failTest() {
- verifier.fail();
+ assertThrows(RuntimeException.class, () -> verifier.fail());
}
-
+
@Test
public void failMsgTest() {
String msg = StringUtils.makeRandomString(5);
@@ -146,7 +146,7 @@ public void failMsgTest() {
assertEquals(msg, e.getMessage());
}
}
-
+
@Test
public void failThrowableTest() {
Exception failure = new Exception();
@@ -157,156 +157,172 @@ public void failThrowableTest() {
assertTrue(failure == e.getCause());
}
}
-
- @Test (expected = RuntimeException.class)
- public void assertTrueFailAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void assertTrueFailAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.assertTrue(false);
}
-
- verifier.assertTrue(false);
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void assertFalseFailAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void assertFalseFailAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.assertFalse(true);
}
-
- verifier.assertFalse(true);
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void assertNullFailAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void assertNullFailAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.assertNull(new Object());
}
-
- verifier.assertNull(new Object());
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void assertNotNullFailAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void assertNotNullFailAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.assertNotNull(null);
}
-
- verifier.assertNotNull(null);
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void assertEqualsObjectFailAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void assertEqualsObjectFailAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.assertEquals(new Object(), new Object());
}
-
- verifier.assertEquals(new Object(), new Object());
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void failTestAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void failTestAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.fail();
}
-
- verifier.fail();
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void failMsgTestAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void failMsgTestAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.fail("foo");
}
-
- verifier.fail("foo");
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
-
- @Test (expected = RuntimeException.class)
- public void failThrowableTestAnotherThreadTest() throws InterruptedException, TimeoutException {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(ASYNC_WAIT_AMOUNT);
- } catch (InterruptedException e) {
- // let thread exit
- return;
+
+ @Test
+ public void failThrowableTestAnotherThreadTest() {
+ assertThrows(RuntimeException.class, () -> {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(ASYNC_WAIT_AMOUNT);
+ } catch (InterruptedException e) {
+ // let thread exit
+ return;
+ }
+
+ verifier.fail(new Exception());
}
-
- verifier.fail(new Exception());
- }
- }).start();
-
- verifier.waitForTest();
+ }).start();
+
+ verifier.waitForTest();
+ });
}
}
diff --git a/src/test/java/org/threadly/test/concurrent/TestConditionTest.java b/src/test/java/org/threadly/test/concurrent/TestConditionTest.java
index 1276051..5d7f141 100644
--- a/src/test/java/org/threadly/test/concurrent/TestConditionTest.java
+++ b/src/test/java/org/threadly/test/concurrent/TestConditionTest.java
@@ -1,11 +1,11 @@
package org.threadly.test.concurrent;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayDeque;
import java.util.Queue;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.threadly.ThreadlyTester;
import org.threadly.util.Clock;
@@ -17,15 +17,15 @@ public void blockTest() {
long startTime = Clock.accurateForwardProgressingMillis();
dc.blockTillTrue((DELAY_TIME * 10) + 5000);
long endTime = Clock.accurateForwardProgressingMillis();
-
+
assertTrue(endTime - startTime >= DELAY_TIME);
assertTrue(endTime - startTime <= DELAY_TIME + (SLOW_MACHINE ? 5000 : 1000));
-
+
startTime = Clock.accurateForwardProgressingMillis();
dc.blockTillTrue(); // should return immediately
assertTrue(Clock.accurateForwardProgressingMillis() - startTime <= 10);
}
-
+
@Test
public void blockFail() {
DelayCondition dc = new DelayCondition(DELAY_TIME * 100);
@@ -37,39 +37,41 @@ public void blockFail() {
assertTrue(Clock.accurateForwardProgressingMillis() - startTime >= DELAY_TIME);
}
}
-
- @Test (expected = RuntimeException.class)
+
+ @Test
public void defaultConstructorFail() {
- TestCondition tc = new TestCondition();
- tc.get();
+ assertThrows(RuntimeException.class, () -> {
+ TestCondition tc = new TestCondition();
+ tc.get();
+ });
}
-
+
@Test
public void supplierPredicateTest() {
Queue values = new ArrayDeque<>(8);
values.add("foo");
values.add("false");
values.add("true");
-
+
new TestCondition(() -> values.remove(), Boolean::parseBoolean).blockTillTrue();
}
-
+
private class DelayCondition extends TestCondition {
private final long delayTime;
private long firstGetTime;
-
+
private DelayCondition(long delayTime) {
this.delayTime = delayTime;
firstGetTime = -1;
}
-
+
@Override
public boolean get() {
if (firstGetTime < 0) {
firstGetTime = Clock.accurateForwardProgressingMillis();
return false;
}
-
+
return Clock.accurateForwardProgressingMillis() - firstGetTime >= delayTime;
}
}
diff --git a/src/test/java/org/threadly/test/concurrent/TestRunnableTest.java b/src/test/java/org/threadly/test/concurrent/TestRunnableTest.java
index ef0eb52..da530a1 100644
--- a/src/test/java/org/threadly/test/concurrent/TestRunnableTest.java
+++ b/src/test/java/org/threadly/test/concurrent/TestRunnableTest.java
@@ -1,10 +1,10 @@
package org.threadly.test.concurrent;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.threadly.ThreadlyTester;
import org.threadly.test.concurrent.TestCondition.ConditionTimeoutException;
import org.threadly.util.Clock;
@@ -12,44 +12,44 @@
@SuppressWarnings("javadoc")
public class TestRunnableTest extends ThreadlyTester {
private TestRunnable instance;
-
- @Before
+
+ @BeforeEach
public void setup() {
instance = new TestRunnable();
}
-
- @After
+
+ @AfterEach
public void cleanup() {
instance = null;
}
-
+
@Test
public void constructorTest() {
assertEquals(0, instance.getRunCount());
assertFalse(instance.ranOnce());
assertFalse(instance.ranConcurrently());
assertEquals(0, instance.getRunDelayInMillis());
-
+
instance = new TestRunnable(DELAY_TIME);
assertEquals(DELAY_TIME, instance.getRunDelayInMillis());
}
-
+
@Test
public void setRunDelayInMillisTest() {
assertEquals(0, instance.getRunDelayInMillis());
instance.setRunDelayInMillis(DELAY_TIME);
assertEquals(DELAY_TIME, instance.getRunDelayInMillis());
}
-
+
@Test
public void runTest() {
TestTestRunnable ttr = new TestTestRunnable();
long start = Clock.accurateForwardProgressingMillis();
-
+
TestUtils.blockTillClockAdvances();
-
+
ttr.run();
-
+
assertTrue(ttr.handleRunStartCalled);
assertTrue(ttr.handleRunFinishCalled);
assertTrue(ttr.startCalledBeforeFinish);
@@ -58,35 +58,35 @@ public void runTest() {
assertTrue(ttr.getDelayTillFirstRun() > 0);
TestUtils.blockTillClockAdvances();
-
+
ttr.run();
-
+
TestUtils.blockTillClockAdvances();
-
+
long now = Clock.accurateForwardProgressingMillis();
assertTrue(ttr.getDelayTillRun(2) <= now - start);
assertTrue(ttr.getDelayTillRun(2) > ttr.getDelayTillFirstRun());
}
-
+
@Test
public void runWithDelay() {
int runCount = TEST_QTY / 2;
instance.setRunDelayInMillis(DELAY_TIME);
-
+
long startTime = Clock.accurateForwardProgressingMillis();
for (int i = 0; i < runCount; i++) {
instance.run();
}
long endTime = Clock.accurateForwardProgressingMillis();
-
+
assertTrue(endTime - startTime >= ((DELAY_TIME * runCount)- ALLOWED_VARIANCE));
}
-
+
@Test
public void blockTillRunTest() {
TestRunnable tr = new TestRunnable() {
private boolean firstRun = true;
-
+
@Override
public void handleRunStart() throws InterruptedException {
if (firstRun) {
@@ -97,73 +97,75 @@ public void handleRunStart() throws InterruptedException {
}
};
new Thread(tr).start();
-
+
long startTime = Clock.accurateForwardProgressingMillis();
tr.blockTillFinished(1000, 2);
long endTime = Clock.accurateForwardProgressingMillis();
-
+
assertTrue(endTime - startTime >= (DELAY_TIME - ALLOWED_VARIANCE));
}
-
- @Test (expected = ConditionTimeoutException.class)
+
+ @Test
public void blockTillRunTestFail() {
- instance.blockTillFinished(DELAY_TIME);
-
- fail("Exception should have thrown");
+ assertThrows(ConditionTimeoutException.class, () -> {
+ instance.blockTillFinished(DELAY_TIME);
+
+ fail("Exception should have thrown");
+ });
}
-
+
@Test
public void ranConcurrentlyTest() {
TestRunnable notConcurrentTR = new TestRunnable();
-
+
notConcurrentTR.run();
notConcurrentTR.run();
assertFalse(notConcurrentTR.ranConcurrently());
-
+
TestRunnable concurrentTR = new TestRunnable() {
private boolean ranOnce = false;
-
+
@Override
public void handleRunStart() {
if (! ranOnce) {
// used to prevent infinite recursion
ranOnce = true;
-
+
this.run();
}
}
};
-
+
concurrentTR.run();
assertTrue(concurrentTR.ranConcurrently());
}
-
+
@Test
public void currentlyRunningTest() {
BlockingTestRunnable btr = new BlockingTestRunnable();
-
+
assertFalse(btr.isRunning());
-
+
new Thread(btr).start();
try {
btr.blockTillStarted();
-
+
assertTrue(btr.isRunning());
} finally {
btr.unblock();
}
}
-
+
private class TestTestRunnable extends TestRunnable {
private boolean handleRunStartCalled = false;
private boolean handleRunFinishCalled = false;
private boolean startCalledBeforeFinish = false;
-
+
@Override
public void handleRunStart() {
handleRunStartCalled = true;
}
-
+
@Override
public void handleRunFinish() {
handleRunFinishCalled = true;
diff --git a/src/test/java/org/threadly/test/concurrent/TestUtilTest.java b/src/test/java/org/threadly/test/concurrent/TestUtilTest.java
index 8a5fd28..a5368b5 100644
--- a/src/test/java/org/threadly/test/concurrent/TestUtilTest.java
+++ b/src/test/java/org/threadly/test/concurrent/TestUtilTest.java
@@ -1,10 +1,10 @@
package org.threadly.test.concurrent;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.threadly.ThreadlyTester;
import org.threadly.concurrent.SingleThreadScheduler;
import org.threadly.concurrent.future.ListenableFuture;
@@ -19,7 +19,7 @@ public void sleepTest() {
long end = Clock.accurateForwardProgressingMillis();
assertTrue(end - start >= (DELAY_TIME - ALLOWED_VARIANCE));
}
-
+
@Test
public void sleepInterruptedTest() {
SingleThreadScheduler sts = new SingleThreadScheduler();
@@ -34,15 +34,15 @@ public void run() {
// spin
}
TestUtils.sleep(DELAY_TIME);
-
+
testThread.interrupt();
}
});
-
+
aboutToSleep.set(true);
TestUtils.sleep(1000 * 20);
// should wake up from interrupt
-
+
assertTrue(Thread.interrupted());
} finally {
sts.shutdownNow();
@@ -51,7 +51,7 @@ public void run() {
}
}
}
-
+
@Test
public void blockTillClockAdvancesTest() {
long before = Clock.accurateTimeMillis();
diff --git a/src/test/java/org/threadly/test/concurrent/TestableSchedulerTest.java b/src/test/java/org/threadly/test/concurrent/TestableSchedulerTest.java
index b60d684..a3b1be2 100644
--- a/src/test/java/org/threadly/test/concurrent/TestableSchedulerTest.java
+++ b/src/test/java/org/threadly/test/concurrent/TestableSchedulerTest.java
@@ -1,6 +1,6 @@
package org.threadly.test.concurrent;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Iterator;
@@ -10,9 +10,9 @@
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.threadly.ThreadlyTester;
import org.threadly.concurrent.CentralThreadlyPool;
import org.threadly.concurrent.DoNothingRunnable;
@@ -24,56 +24,56 @@
@SuppressWarnings("javadoc")
public class TestableSchedulerTest extends ThreadlyTester {
protected TestableScheduler scheduler;
-
- @Before
+
+ @BeforeEach
public void setup() {
scheduler = new TestableScheduler();
}
-
- @After
+
+ @AfterEach
public void cleanup() {
scheduler = null;
}
-
+
private static List getRunnableList() {
List result = new ArrayList<>(TEST_QTY);
for (int i = 0; i < TEST_QTY; i++) {
result.add(new TestRunnable());
}
-
+
return result;
}
-
+
private static List getCallableList() {
List result = new ArrayList<>(TEST_QTY);
for (int i = 0; i < TEST_QTY; i++) {
result.add(new TestCallable());
}
-
+
return result;
}
-
+
@Test
public void isShutdownTest() {
assertFalse(scheduler.isShutdown());
}
-
+
@Test
public void getDefaultPriorityTest() {
assertEquals(TaskPriority.High, scheduler.getDefaultPriority());
assertEquals(TaskPriority.Low, new TestableScheduler(TaskPriority.Low, 100).getDefaultPriority());
}
-
+
@Test
public void getMaxWaitForLowPriorityTest() {
assertEquals(100, new TestableScheduler(TaskPriority.Low, 100).getMaxWaitForLowPriority());
}
-
+
@Test
public void getQueuedTaskCountTest() {
for (int i = 0; i < TEST_QTY; i++) {
TaskPriority priority = i % 2 == 0 ? TaskPriority.High : TaskPriority.Low;
-
+
assertEquals(i, scheduler.getQueuedTaskCount());
assertEquals(i / 2, scheduler.getQueuedTaskCount(priority));
@@ -84,15 +84,15 @@ public void getQueuedTaskCountTest() {
}
}
}
-
+
@Test
public void getWaitingForExecutionTaskCountTest() {
for (int i = 0; i < TEST_QTY; i++) {
TaskPriority priority = i % 2 == 0 ? TaskPriority.High : TaskPriority.Low;
-
+
assertEquals(i, scheduler.getWaitingForExecutionTaskCount());
assertEquals(i / 2, scheduler.getWaitingForExecutionTaskCount(priority));
-
+
if (i <= 5) {
scheduler.submit(DoNothingRunnable.instance(), priority);
} else {
@@ -101,37 +101,37 @@ public void getWaitingForExecutionTaskCountTest() {
scheduler.submitScheduled(DoNothingRunnable.instance(), 10_000, priority); // task should be ignored
}
}
-
+
@Test
public void getActiveTaskCountTest() {
BlockingTestRunnable btr = new BlockingTestRunnable();
try {
scheduler.execute(btr);
-
+
assertEquals(0, scheduler.getActiveTaskCount());
-
+
CentralThreadlyPool.isolatedTaskPool().execute(() -> scheduler.tick());
-
+
new TestCondition(() -> scheduler.getActiveTaskCount() == 1).blockTillTrue();
} finally {
btr.unblock();
}
}
-
+
@Test
public void lastTickTimeTest() {
long now = Clock.lastKnownTimeMillis();
-
+
scheduler.tick(now + 1000);
-
+
assertEquals(now + 1000, scheduler.getLastTickTime());
}
-
+
@Test
public void advanceWithoutHandlerThrowsRuntimeExceptionTest() {
RuntimeException failure = new StackSuppressedRuntimeException();
scheduler.execute(new TestRuntimeFailureRunnable(failure));
-
+
try {
scheduler.advance(10);
fail("Exception should have thrown");
@@ -139,29 +139,29 @@ public void advanceWithoutHandlerThrowsRuntimeExceptionTest() {
assertTrue(e == failure);
}
}
-
+
@Test
public void advanceHandlesRuntimeExceptionTest() {
RuntimeException failure = new StackSuppressedRuntimeException();
final AtomicReference handledException = new AtomicReference<>(null);
scheduler.execute(new TestRuntimeFailureRunnable(failure));
-
+
int runCount = scheduler.advance(10, new ExceptionHandler() {
@Override
public void handleException(Throwable thrown) {
handledException.set(thrown);
}
});
-
+
assertEquals(1, runCount);
assertTrue(handledException.get() == failure);
}
-
+
@Test
public void tickWithoutHandlerThrowsRuntimeExceptionTest() {
RuntimeException failure = new StackSuppressedRuntimeException();
scheduler.execute(new TestRuntimeFailureRunnable(failure));
-
+
try {
scheduler.tick();
fail("Exception should have thrown");
@@ -169,44 +169,44 @@ public void tickWithoutHandlerThrowsRuntimeExceptionTest() {
assertTrue(e == failure);
}
}
-
+
@Test
public void tickHandlesRuntimeExceptionTest() {
RuntimeException failure = new StackSuppressedRuntimeException();
final AtomicReference handledException = new AtomicReference<>(null);
scheduler.execute(new TestRuntimeFailureRunnable(failure));
-
+
int runCount = scheduler.tick(new ExceptionHandler() {
@Override
public void handleException(Throwable thrown) {
handledException.set(thrown);
}
});
-
+
assertEquals(1, runCount);
assertTrue(handledException.get() == failure);
}
-
+
@Test
public void advanceTest() {
long now = scheduler.getLastTickTime();
scheduler.advance(1000);
-
+
assertEquals(now + 1000, scheduler.getLastTickTime());
}
-
+
@Test
public void advanceThenTickTest() {
scheduler.execute(DoNothingRunnable.instance());
scheduler.advance(1000 * 10);
-
+
TestRunnable tr = new TestRunnable();
scheduler.execute(tr);
-
+
assertEquals(1, scheduler.tick());
assertTrue(tr.ranOnce());
}
-
+
@Test
public void executeTest() {
List runnables = getRunnableList();
@@ -215,24 +215,24 @@ public void executeTest() {
while (it.hasNext()) {
scheduler.execute(it.next());
}
-
+
// all should run now
assertEquals(TEST_QTY, scheduler.tick(Clock.lastKnownTimeMillis()));
-
+
it = runnables.iterator();
while (it.hasNext()) {
assertEquals(1, it.next().getRunCount());
}
-
+
// verify no more run after a second tick
assertEquals(scheduler.tick(), 0);
-
+
it = runnables.iterator();
while (it.hasNext()) {
assertEquals(1, it.next().getRunCount());
}
}
-
+
@Test
public void submitRunnableTest() {
List runnables = getRunnableList();
@@ -243,29 +243,29 @@ public void submitRunnableTest() {
assertNotNull(future);
futures.add(future);
}
-
+
// all should run now
assertEquals(TEST_QTY, scheduler.tick(Clock.lastKnownTimeMillis()));
-
+
it = runnables.iterator();
while (it.hasNext()) {
assertEquals(1, it.next().getRunCount());
}
-
+
// verify no more run after a second tick
assertEquals(0, scheduler.tick());
-
+
it = runnables.iterator();
while (it.hasNext()) {
assertEquals(1, it.next().getRunCount());
}
-
+
Iterator> futureIt = futures.iterator();
while (futureIt.hasNext()) {
assertTrue(futureIt.next().isDone());
}
}
-
+
@Test
public void submitCallableTest() throws InterruptedException, ExecutionException {
List callables = getCallableList();
@@ -276,10 +276,10 @@ public void submitCallableTest() throws InterruptedException, ExecutionException
assertNotNull(future);
futures.add(future);
}
-
+
// all should run now
assertEquals(TEST_QTY, scheduler.tick(Clock.lastKnownTimeMillis()));
-
+
it = callables.iterator();
while (it.hasNext()) {
assertTrue(it.next().isDone());
@@ -290,19 +290,19 @@ public void submitCallableTest() throws InterruptedException, ExecutionException
while (futureIt.hasNext()) {
Future