mirror of https://github.com/sbt/sbt.git
91 lines
3.3 KiB
Scala
91 lines
3.3 KiB
Scala
package sbt
|
|
|
|
import java.io.File
|
|
import org.scalacheck.{Arbitrary, Gen, Prop, Properties}
|
|
import Prop._
|
|
|
|
import Process._
|
|
|
|
private[this] object ProcessSpecification extends Properties("Process I/O")
|
|
{
|
|
implicit val exitCodeArb: Arbitrary[Array[Byte]] = Arbitrary(Gen.choose(0, 10) flatMap { size => Gen.resize(size, Arbitrary.arbArray[Byte].arbitrary) })
|
|
|
|
/*property("Correct exit code") = forAll( (exitCode: Byte) => checkExit(exitCode))
|
|
property("#&& correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #&& _)(_ && _))
|
|
property("#|| correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #|| _)(_ || _))
|
|
property("### correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ ### _)( (x,latest) => latest))*/
|
|
property("Pipe to output file") = forAll( (data: Array[Byte]) => checkFileOut(data))
|
|
property("Pipe to input file") = forAll( (data: Array[Byte]) => checkFileIn(data))
|
|
property("Pipe to process") = forAll( (data: Array[Byte]) => checkPipe(data))
|
|
|
|
private def checkBinary(codes: Array[Byte])(reduceProcesses: (ProcessBuilder, ProcessBuilder) => ProcessBuilder)(reduceExit: (Boolean, Boolean) => Boolean) =
|
|
{
|
|
(codes.length > 1) ==>
|
|
{
|
|
val unsignedCodes = codes.map(unsigned)
|
|
val exitCode = unsignedCodes.map(code => Process(process("sbt.exit " + code))).reduceLeft(reduceProcesses) !
|
|
val expectedExitCode = unsignedCodes.map(toBoolean).reduceLeft(reduceExit)
|
|
toBoolean(exitCode) == expectedExitCode
|
|
}
|
|
}
|
|
private def toBoolean(exitCode: Int) = exitCode == 0
|
|
private def checkExit(code: Byte) =
|
|
{
|
|
val exitCode = unsigned(code)
|
|
(process("sbt.exit " + exitCode) !) == exitCode
|
|
}
|
|
private def checkFileOut(data: Array[Byte]) =
|
|
{
|
|
withData(data) { (temporaryFile, temporaryFile2) =>
|
|
val catCommand = process("sbt.cat " + temporaryFile.getAbsolutePath)
|
|
catCommand #> temporaryFile2
|
|
}
|
|
}
|
|
private def checkFileIn(data: Array[Byte]) =
|
|
{
|
|
withData(data) { (temporaryFile, temporaryFile2) =>
|
|
val catCommand = process("sbt.cat")
|
|
temporaryFile #> catCommand #> temporaryFile2
|
|
}
|
|
}
|
|
private def checkPipe(data: Array[Byte]) =
|
|
{
|
|
withData(data) { (temporaryFile, temporaryFile2) =>
|
|
val catCommand = process("sbt.cat")
|
|
temporaryFile #> catCommand #| catCommand #> temporaryFile2
|
|
}
|
|
}
|
|
private def temp() = File.createTempFile("sbt", "")
|
|
private def withData(data: Array[Byte])(f: (File, File) => ProcessBuilder) =
|
|
{
|
|
val temporaryFile1 = temp()
|
|
val temporaryFile2 = temp()
|
|
try
|
|
{
|
|
IO.write(temporaryFile1, data)
|
|
val process = f(temporaryFile1, temporaryFile2)
|
|
( process ! ) == 0 &&
|
|
{
|
|
val b1 = IO.readBytes(temporaryFile1)
|
|
val b2 = IO.readBytes(temporaryFile2)
|
|
b1 sameElements b2
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
temporaryFile1.delete()
|
|
temporaryFile2.delete()
|
|
}
|
|
}
|
|
private def unsigned(b: Byte): Int = ((b: Int) +256) % 256
|
|
private def process(command: String) =
|
|
{
|
|
val ignore = echo // just for the compile dependency so that this test is rerun when TestedProcess.scala changes, not used otherwise
|
|
|
|
val thisClasspath = List(getSource[ScalaObject], getSource[IO.type], getSource[SourceTag]).mkString(File.pathSeparator)
|
|
"java -cp " + thisClasspath + " " + command
|
|
}
|
|
private def getSource[T : Manifest]: String =
|
|
IO.classLocationFile[T].getAbsolutePath
|
|
}
|
|
private trait SourceTag |