diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1456c1da..a54081ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,21 +49,32 @@ jobs: steps: - uses: actions/checkout@v7 - uses: actions/setup-java@v6 + id: test-jdk with: distribution: 'zulu' java-version: ${{ matrix.version }} + # sbt 2 requires JDK 17+. Run sbt on JDK 21 and fork tests on the matrix JDK via TEST_JAVA_HOME + - uses: actions/setup-java@v6 + with: + distribution: 'zulu' + java-version: '21' - uses: actions/cache@v6 with: path: ~/.cache key: ${{ runner.os }}-jdk${{ matrix.version }}-${{ hashFiles('**/*.sbt') }} restore-keys: ${{ runner.os }}-jdk${{ matrix.version }}- - name: Test + env: + TEST_JAVA_HOME: ${{ steps.test-jdk.outputs.path }} run: | if [ "${{ matrix.version }}" -ge "24" ]; then export _JAVA_OPTIONS="--enable-native-access=ALL-UNNAMED" fi - ./sbt test + # testFull: sbt 2's test skips tests that passed in a cached previous run + ./sbt testFull - name: JAR Integration Test + env: + TEST_JAVA_HOME: ${{ steps.test-jdk.outputs.path }} run: ./script/test-jar-integration.sh test-musl: strategy: @@ -102,9 +113,10 @@ jobs: shell: bash run: | ./sbt compile - arch=$(java -cp target/classes org.xerial.snappy.OSInfo --arch) + classes=$(find target -type d -path '*/snappy-java/classes' | head -1) + arch=$(java -cp "$classes" org.xerial.snappy.OSInfo --arch) echo "detected arch: $arch" test "$arch" = "${{ matrix.expected_arch }}" - name: Test shell: bash - run: ./sbt test + run: ./sbt testFull diff --git a/CLAUDE.md b/CLAUDE.md index 37640e66..a259fbad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,9 +14,15 @@ snappy-java is a Java port of Google's Snappy compression library, providing fas # Enter sbt console ./sbt -# Run tests +# Run tests (sbt 2 skips tests that passed in a cached previous run) ./sbt test +# Run all tests regardless of the cache +./sbt testFull + +# sbt 2 requires JDK 17+. To run tests on an older JDK, fork them on another JDK +TEST_JAVA_HOME=/path/to/jdk8 ./sbt testFull + # Run tests matching a pattern ./sbt "testOnly *BitShuffleTest" @@ -131,7 +137,7 @@ The project uses sbt's built-in Sonatype integration for publishing: ### Common Development Tasks - When making changes to native code, rebuild with `make clean-native native` - For Java/Scala changes, use `./sbt ~test` for continuous testing -- Always test on multiple JDK versions if possible (8, 11, 17, 21) +- Always test on multiple JDK versions if possible (8, 11, 17, 21, 25), using `TEST_JAVA_HOME` for JDKs older than 17 ### Native Code Testing - Use make clean-native native for testing native code diff --git a/build.sbt b/build.sbt index 99a90541..b4dd91a8 100644 --- a/build.sbt +++ b/build.sbt @@ -13,12 +13,12 @@ ThisBuild / publishTo := { localStaging.value } -licenses := Seq("Apache-2.0" -> url("https://www.apache.org/licenses/LICENSE-2.0.html")) -homepage := Some(url("https://github.com/xerial/snappy-java")) +licenses := Seq("Apache-2.0" -> uri("https://www.apache.org/licenses/LICENSE-2.0.html")) +homepage := Some(uri("https://github.com/xerial/snappy-java")) scmInfo := Some( ScmInfo( - browseUrl = url("https://github.com/xerial/snappy-java"), + browseUrl = uri("https://github.com/xerial/snappy-java"), connection = "scm:git@github.com:xerial/snappy-java.git" ) ) @@ -29,7 +29,7 @@ developers := id = "leo", name = "Taro L. Saito", email = "leo@xerial.org", - url = url("http://xerial.org/leo") + url = uri("http://xerial.org/leo") ) ) @@ -38,7 +38,7 @@ ThisBuild / dynverSonatypeSnapshots := true // Use coursier friendly version separator ThisBuild / dynverSeparator := "-" -ThisBuild / scalaVersion := "3.7.1" +ThisBuild / scalaVersion := "3.9.0" // For building jars for JDK8 ThisBuild / javacOptions ++= { @@ -64,6 +64,15 @@ doc / javacOptions := { // Configuration for SnappyHadoopCompatibleOutputStream testing Test / fork := true +// sbt 2 itself requires JDK 17+. To test on older JDKs (e.g., 8), run sbt on JDK 17+ +// and set TEST_JAVA_HOME to the JDK the forked test JVM should use. +// Set it on forkOptions only, since Test / javaHome would also switch javac to that JDK. +Test / forkOptions := + Def.uncached { + val opts = (Test / forkOptions).value + sys.env.get("TEST_JAVA_HOME").fold(opts)(home => opts.withJavaHome(file(home))) + } + val libTemp = { val path = s"${System.getProperty("java.io.tmpdir")}/snappy_test_${System.currentTimeMillis()}" // certain older Linux systems (debian/trusty in Travis CI) requires the libsnappy.so, loaded by @@ -98,8 +107,10 @@ libraryDependencies ++= "org.codehaus.plexus" % "plexus-classworlds" % "2.12.1" % "test", "org.osgi" % "org.osgi.core" % "6.0.0" % "provided", "com.github.sbt" % "junit-interface" % "0.13.3" % "test", - "org.apache.hadoop" % "hadoop-common" % "3.4.3" % "test" exclude - ("org.xerial.snappy", "snappy-java") + ("org.apache.hadoop" % "hadoop-common" % "3.4.3" % "test").exclude( + "org.xerial.snappy", + "snappy-java" + ) ) packageOptions += Package.ManifestAttributes("Automatic-Module-Name" -> "org.xerial.snappy") diff --git a/project/build.properties b/project/build.properties index d0598eb7..570ab8e6 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1 @@ -sbt.version=1.13.0 - +sbt.version=2.0.10 diff --git a/project/plugins.sbt b/project/plugins.sbt index 7a718b72..f60e0ab3 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.2") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.11.0-RC1") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.6.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") diff --git a/script/test-jar-integration.sh b/script/test-jar-integration.sh index af345ad7..9caa5fdd 100755 --- a/script/test-jar-integration.sh +++ b/script/test-jar-integration.sh @@ -5,8 +5,11 @@ echo "==========================================" echo "Snappy-Java Integration Test" echo "==========================================" +# sbt 2 requires JDK 17+, so CI may run sbt on a newer JDK and test on TEST_JAVA_HOME +JAVA_BIN=${TEST_JAVA_HOME:+$TEST_JAVA_HOME/bin/} + # Detect Java version -JAVA_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed 's/^1\.//' | cut -d'.' -f1) +JAVA_VERSION=$(${JAVA_BIN}java -version 2>&1 | head -1 | cut -d'"' -f2 | sed 's/^1\.//' | cut -d'.' -f1) echo "Java version: $JAVA_VERSION" # Build the JAR @@ -15,7 +18,7 @@ echo "Building JAR..." ./sbt package # Find the JAR -JAR_FILE=$(ls -t target/snappy-java-*.jar | grep -v sources | grep -v javadoc | head -1) +JAR_FILE=$(ls -t $(find target -name 'snappy-java-*.jar') | grep -v -e sources -e javadoc -e tests | head -1) if [ -z "$JAR_FILE" ]; then echo "ERROR: Could not find snappy-java JAR" exit 1 @@ -33,7 +36,7 @@ cp src/test/resources/integration/SnappyIntegrationTest.java "$TEMP_DIR/" # Compile test echo "" echo "Compiling test program..." -javac -cp "$JAR_FILE" -d "$TEMP_DIR" "$TEMP_DIR/SnappyIntegrationTest.java" +${JAVA_BIN}javac -cp "$JAR_FILE" -d "$TEMP_DIR" "$TEMP_DIR/SnappyIntegrationTest.java" # Run test WITHOUT --enable-native-access flag echo "" @@ -42,7 +45,7 @@ echo "Running test (WITHOUT --enable-native-access flag)..." echo "==========================================" cd "$TEMP_DIR" -java -cp ".:$OLDPWD/$JAR_FILE" SnappyIntegrationTest 2>&1 +${JAVA_BIN}java -cp ".:$OLDPWD/$JAR_FILE" SnappyIntegrationTest 2>&1 EXIT_CODE=$? cd - > /dev/null diff --git a/src/test/java/org/xerial/snappy/SnappyLoaderTest.java b/src/test/java/org/xerial/snappy/SnappyLoaderTest.java index 4bfeb1f5..8321e9e0 100755 --- a/src/test/java/org/xerial/snappy/SnappyLoaderTest.java +++ b/src/test/java/org/xerial/snappy/SnappyLoaderTest.java @@ -94,7 +94,7 @@ public void loadSnappyByDiffentClassloadersInTheSameJVM() } // Prepare the child class loaders which can load Snappy.class - URL classPath = new File("target/classes").toURI().toURL(); + URL classPath = Snappy.class.getProtectionDomain().getCodeSource().getLocation(); ClassRealm L1 = cw.newRealm("l1", URLClassLoader.newInstance(new URL[] {classPath}, parent)); ClassRealm L2 = cw.newRealm("l2", URLClassLoader.newInstance(new URL[] {classPath}, parent));