sbt/launch/src/test/scala/LocksTest.scala

56 lines
1.8 KiB
Scala

package xsbt.boot
import org.scalacheck._
import Prop._
import java.io.File
/** These mainly test that things work in the uncontested case and that no OverlappingFileLockExceptions occur.
* There is no real locking testing, just the coordination of locking.*/
object LocksTest extends Properties("Locks")
{
property("Lock in nonexisting directory") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "doesntexist/lock")
Locks(lockFile, callTrue)
}
}
property("Uncontested re-entrant lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
Locks(lockFile, callLocked(lockFile)) &&
Locks(lockFile, callLocked(lockFile))
}
}
property("Uncontested double lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFileA = new File(dir, "lockA")
val lockFileB = new File(dir, "lockB")
Locks(lockFileA, callLocked(lockFileB)) &&
Locks(lockFileB, callLocked(lockFileA))
}
}
property("Contested single lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
forkFold(2000){i => Locks(lockFile, callTrue) }
}
}
private def spec(f: => Boolean): Prop = Prop { _ => Result(if(f) True else False) }
private def call[T](impl: => T) = new java.util.concurrent.Callable[T] { def call = impl }
private def callLocked(lockFile: File) = call { Locks(lockFile, callTrue) }
private lazy val callTrue = call { true }
private def forkFold(n: Int)(impl: Int => Boolean): Boolean =
(true /: forkWait(n)(impl))(_ && _)
private def forkWait(n: Int)(impl: Int => Boolean): Iterable[Boolean] =
{
import scala.concurrent.ops.future
val futures = (0 until n).map { i => future { impl(i) } }
futures.toList.map(_())
}
}