From 46d7e38b4651caff2a7fb9dc9ee1aa398807db44 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Tue, 9 Oct 2018 14:37:57 -0700 Subject: Add testkit module --- .../postgres/DockerPostgresFixtureDatabase.scala | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala (limited to 'core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala') diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala new file mode 100644 index 0000000..3e00bf5 --- /dev/null +++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala @@ -0,0 +1,74 @@ +package xyz.driver.core.testkit +package postgres + +import java.net.ServerSocket + +import org.scalatest.{BeforeAndAfterAll, Suite} +import slick.jdbc.PostgresProfile +import xyz.driver.core.using + +import scala.concurrent.Await +import scala.concurrent.duration._ + +trait DockerPostgresFixtureDatabase + extends FixtureDatabase[PostgresProfile] with DockerPostgresDatabase with BeforeAndAfterAll { + self: Suite => + private val dbName: String = sys.env.getOrElse("TEST_DB_NAME", "postgres") + private val username: String = sys.env.getOrElse("TEST_DB_USERNAME", "postgres") + private val password: String = sys.env.getOrElse("TEST_DB_PASSWORD", "postgres") + private val port: Int = sys.env.get("TEST_DB_PORT").fold(getRandomPort())(_.toInt) + + private val enabled: Boolean = !sys.env.get("DISABLE_DOCKER_TEST_DB").contains("true") + + protected val connectionTimeout: Duration = 16.seconds + + final val profile = PostgresProfile + final override val database = profile.backend.Database.forURL( + driver = "org.postgresql.Driver", + url = s"jdbc:postgresql://localhost:$port/$dbName", + user = username, + password = password) + + object driverDatabase extends xyz.driver.core.database.Database { + override val profile = self.profile + override val database = self.database + } + + private def getRandomPort(): Int = using(new ServerSocket(0))(_.getLocalPort()) + + @SuppressWarnings(Array("org.wartremover.warts.Var")) + private var dockerContainerId: Option[String] = None + + private def waitForContainer(): Unit = { + import concurrent.ExecutionContext.Implicits.global + import profile.api._ + + val expiration = System.currentTimeMillis() + connectionTimeout.toMillis + + val query = sql"SELECT 1;".as[Int] + def dbReady = Await.result( + database + .run(query) + .map(_ == Vector(1)) + .recover({ case _: org.postgresql.util.PSQLException => false }), + connectionTimeout + ) + + while (!dbReady && System.currentTimeMillis() < expiration) { + Thread.sleep(100) + } + } + + override protected def beforeAll(): Unit = { + if (enabled) { + dockerContainerId = Some(super.setupDockerDatabase(username, password, dbName, port)) + waitForContainer() + } + super.beforeAll() + } + + override protected def afterAll(): Unit = { + try super.afterAll() + finally dockerContainerId.foreach(killDockerDatabase) + } +} -- cgit v1.2.3