diff --git a/build.sbt b/build.sbt index ae2cf436..6a492d3a 100644 --- a/build.sbt +++ b/build.sbt @@ -80,8 +80,9 @@ val io = (project in file("io")) commonSettings, name := "IO", libraryDependencies ++= { - Vector(scalaCompiler.value % Test, scalaCheck % Test, scalatest % Test) + Vector(scalaCompiler.value % Test, scalaVerify % Test, scalaCheck % Test, scalatest % Test) } ++ Vector(swovalFiles), + testFrameworks += new TestFramework("verify.runner.Framework"), Test / fork := System.getProperty("sbt.test.fork", "false") == "true", Test / testForkedParallel := true, Compile / generateContrabands / sourceManaged := baseDirectory.value / "src" / "main" / "contraband-scala", diff --git a/io/src/main/scala/sbt/internal/io/Retry.scala b/io/src/main/scala/sbt/internal/io/Retry.scala index ebfc0668..2d660655 100644 --- a/io/src/main/scala/sbt/internal/io/Retry.scala +++ b/io/src/main/scala/sbt/internal/io/Retry.scala @@ -34,19 +34,19 @@ private[sbt] object Retry { excludedExceptions: Class[? <: IOException]*, ): T = { require(limit >= 1, "limit must be 1 or higher: was: " + limit) - def filter(e: Exception): Boolean = excludedExceptions match { + def filter(e: Throwable): Boolean = excludedExceptions match { case s if s.nonEmpty => !excludedExceptions.exists(_.isAssignableFrom(e.getClass)) case _ => true } var attempt = 1 - var firstException: IOException = null + var firstException: Throwable = null while (attempt <= limit) { try { return f } catch { - case e: IOException if filter(e) => + case NonFatal(e) if filter(e) => if (firstException == null) firstException = e // https://github.com/sbt/io/issues/295 // On Windows, we're seeing java.nio.file.AccessDeniedException with sleep(0). diff --git a/io/src/test/scala/sbt/internal/io/RetrySpec.scala b/io/src/test/scala/sbt/internal/io/RetrySpec.scala index 298f3fe4..8cbdcde9 100644 --- a/io/src/test/scala/sbt/internal/io/RetrySpec.scala +++ b/io/src/test/scala/sbt/internal/io/RetrySpec.scala @@ -14,11 +14,9 @@ package sbt.internal.io import java.io.IOException import java.util.concurrent.atomic.AtomicInteger -import org.scalatest.flatspec.AnyFlatSpec - -final class RetrySpec extends AnyFlatSpec { +object RetrySpec extends verify.BasicTestSuite { private val noExcluded: List[Class[? <: IOException]] = List[Class[? <: IOException]]() - "retry" should "throw first exception after number of failures" in { + test("retry should throw first exception after number of failures") { val i = new AtomicInteger() def throww(): Any = throw new IOException(i.incrementAndGet().toString) try { @@ -31,7 +29,7 @@ final class RetrySpec extends AnyFlatSpec { } } - "retry" should "throw recover" in { + test("retry should throw recover") { for (recoveryStep <- (1 to 14)) { val i = new AtomicInteger() val value = Retry( @@ -46,4 +44,13 @@ final class RetrySpec extends AnyFlatSpec { assert(value == "recover") } } + + test("retry should recover from non-IO exceptions") { + val i = new AtomicInteger() + def throww(): Any = + if (i.incrementAndGet() == 5) 0 + else ??? + Retry(throww()) + () + } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 7ea746b7..a47e7f48 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,6 +11,7 @@ object Dependencies { "org.scala-lang" % "scala-compiler" % v } + val scalaVerify = "com.eed3si9n.verify" %% "verify" % "1.0.0" val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.18.1" val scalatest = "org.scalatest" %% "scalatest" % "3.2.19" val swovalFiles = "com.swoval" % "file-tree-views" % "2.1.12" diff --git a/project/build.properties b/project/build.properties index abbbce5d..73df629a 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.10.7