summaryrefslogtreecommitdiff
path: root/crashboxd/src/test/scala/io/crashbox/ci
diff options
context:
space:
mode:
Diffstat (limited to 'crashboxd/src/test/scala/io/crashbox/ci')
-rw-r--r--crashboxd/src/test/scala/io/crashbox/ci/BuildStageSpec.scala63
-rw-r--r--crashboxd/src/test/scala/io/crashbox/ci/DockerExecutorSpec.scala78
2 files changed, 134 insertions, 7 deletions
diff --git a/crashboxd/src/test/scala/io/crashbox/ci/BuildStageSpec.scala b/crashboxd/src/test/scala/io/crashbox/ci/BuildStageSpec.scala
new file mode 100644
index 0000000..a3a68b6
--- /dev/null
+++ b/crashboxd/src/test/scala/io/crashbox/ci/BuildStageSpec.scala
@@ -0,0 +1,63 @@
+package io.crashbox.ci
+
+import akka.actor.ActorSystem
+import akka.stream.{ ClosedShape, KillSwitch }
+import akka.stream.scaladsl.{ GraphDSL, RunnableGraph, Sink, Source }
+import akka.stream.{ ActorMaterializer, FanInShape2 }
+import java.io.{ ByteArrayOutputStream, File }
+import java.nio.file.Files
+import org.scalatest._
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+class BuildStageSpec extends FlatSpec with Matchers with DockerSuite{
+
+ implicit val materializer = ActorMaterializer()
+
+ val exec = new DockerExecutor
+
+ def withTmp[A](action: (File, ByteArrayOutputStream) => A): A = {
+ val dir = Files.createTempDirectory("crashbox-build-stage-test").toFile
+ val out = new ByteArrayOutputStream(1024)
+ try action(dir, out)
+ finally dir.delete()
+ }
+
+ "BuildStage" should "have a test!" in {
+ withTmp{ case (dir, out) =>
+ val taskDef = TaskDef(DockerEnvironment("crashbox"), "sleep 100; exit 0")
+
+ val resultSink = Sink.foreach[Builder.BuildState](x => println(x))
+
+ val graph = RunnableGraph.fromGraph(GraphDSL.create(resultSink) {
+ implicit b => sink =>
+ import GraphDSL.Implicits._
+
+ val builder = b.add(new BuildStage(exec, _ => dir, _ => out))
+
+ val submissions = b.add(
+ Source.repeat(TaskId("123", 2) -> taskDef))
+ val cancellations = b.add(
+ Source.tick(10.seconds, 10.seconds, TaskId("0", 0)))
+
+ val ks = b.add(KillSwitch)
+
+ submissions ~> builder.in0
+ cancellations ~> builder.in1
+
+ builder.out ~> sink
+
+ ClosedShape
+ })
+
+ graph.run()
+ Thread.sleep(30000)
+ println("terminating")
+ Await.result(system.terminate(), 60.seconds)
+ println("teminated")
+ Thread.sleep(5000)
+ println("eot")
+ }
+
+ }
+}
diff --git a/crashboxd/src/test/scala/io/crashbox/ci/DockerExecutorSpec.scala b/crashboxd/src/test/scala/io/crashbox/ci/DockerExecutorSpec.scala
index 2b6dce7..23cbced 100644
--- a/crashboxd/src/test/scala/io/crashbox/ci/DockerExecutorSpec.scala
+++ b/crashboxd/src/test/scala/io/crashbox/ci/DockerExecutorSpec.scala
@@ -1,5 +1,6 @@
package io.crashbox.ci
+import com.spotify.docker.client.DockerClient.ListContainersParam
import java.io.{ByteArrayOutputStream, File}
import java.nio.file.Files
@@ -9,6 +10,69 @@ import scala.concurrent.duration._
import akka.actor.ActorSystem
import org.scalatest._
+import scala.util.Random
+
+
+trait DockerSuite extends Suite with BeforeAndAfterAll { self =>
+
+ private val name = self.toString()
+
+ private def withTmp[A](action: File => A): A = {
+ val dir = Files.createTempDirectory("crashbox-docker-test-" + name).toFile
+ try action(dir)
+ finally dir.delete()
+ }
+
+ val baseImage = "debian:jessie-backports"
+ val dockerImage = "crashbox"
+ val dockerTimeout = 30.seconds
+ val dockerLabel = "test-" + Random.nextInt()
+
+ implicit val system = ActorSystem("crashbox-docker-test-" + name)
+ import system.dispatcher
+ val executor = new DockerExecutor {
+ override def label = dockerLabel
+ }
+
+ def buildImage(): Unit = {
+ println("Pulling base docker image for running docker tests")
+ executor.dockerClient.pull(baseImage)
+
+ withTmp { dir =>
+ println("Adapting base image for tests")
+ val modifications = s"""|FROM $baseImage
+ |RUN adduser crashbox
+ |USER crashbox
+ |""".stripMargin
+ Files.write((new File(dir, "Dockerfile")).toPath, modifications.getBytes)
+ executor.dockerClient.build(dir.toPath, dockerImage)
+ }
+ }
+
+ def runningDockers: Seq[String] = {
+ val stale = executor.dockerClient
+ .listContainers(
+ ListContainersParam.withLabel("crashbox", dockerLabel)
+ ).asScala
+ stale.map(_.id())
+ }
+
+ override def beforeAll: Unit = {
+ buildImage()
+ }
+
+ override def afterAll: Unit = {
+ val running = runningDockers
+ running.foreach { id =>
+ executor.dockerClient.stopContainer(id, 0)
+ executor.dockerClient.removeContainer(id)
+ }
+ require(running.isEmpty, "Docker containers were left running after unit tests")
+ require(runningDockers.isEmpty, "Could not delete left over docker containers.")
+ }
+
+}
+
class DockerExecutorSpec
extends FlatSpec
@@ -52,13 +116,13 @@ class DockerExecutorSpec
def run[A](script: String)(tests: (Int, File, String) => A): A = withTmp {
dir =>
- val out = new ByteArrayOutputStream(1024)
- val awaitable = for (id <- exec.start(image, script, dir, out);
- status <- exec.result(id)) yield {
- status
- }
- val status = Await.result(awaitable, timeout)
- tests(status, dir, new String(out.toByteArray()).trim())
+ val out = new ByteArrayOutputStream(1024)
+ val awaitable = for (id <- exec.start(image, script, dir, out);
+ status <- exec.result(id)) yield {
+ status
+ }
+ val status = Await.result(awaitable, timeout)
+ tests(status, dir, new String(out.toByteArray()).trim())
}
"DockerExecutor" should "return expected exit codes" in {