aboutsummaryrefslogtreecommitdiff
path: root/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres
diff options
context:
space:
mode:
Diffstat (limited to 'core-testkit/src/main/scala/xyz/driver/core/testkit/postgres')
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala46
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala74
2 files changed, 120 insertions, 0 deletions
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala
new file mode 100644
index 0000000..41e6e0d
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala
@@ -0,0 +1,46 @@
+package xyz.driver.core.testkit
+package postgres
+
+import xyz.driver.core.make
+
+trait DockerPostgresDatabase {
+ import com.spotify.docker.client._
+ import com.spotify.docker.client.messages._
+
+ lazy val dockerClient: DockerClient = DefaultDockerClient.fromEnv().build()
+
+ val postgresVersion: String = "9.6"
+
+ def setupDockerDatabase(
+ username: String = "postgres",
+ password: String = "postgres",
+ database: String = "postgres",
+ hostPort: Int = 15432): String = {
+ import collection.JavaConverters._
+
+ dockerClient.pull(s"postgres:$postgresVersion")
+
+ val portBindings: Map[String, List[PortBinding]] = Map("5432" -> List(PortBinding.of("0.0.0.0", hostPort)))
+ val portBindingsJava = portBindings.mapValues(_.asJava).asJava
+ val hostConfig = HostConfig.builder().portBindings(portBindingsJava).build()
+ val containerConfig =
+ ContainerConfig
+ .builder()
+ .hostConfig(hostConfig)
+ .image(s"postgres:$postgresVersion")
+ .exposedPorts("5432")
+ .env(
+ s"POSTGRES_USER=$username",
+ s"POSTGRES_DB=$database",
+ s"POSTGRES_PASSWORD=$password"
+ )
+ .build()
+
+ make(dockerClient.createContainer(containerConfig).id())(dockerClient.startContainer)
+ }
+
+ def killDockerDatabase(containerId: String): Unit = {
+ dockerClient.killContainer(containerId)
+ dockerClient.removeContainer(containerId)
+ }
+}
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)
+ }
+}