From 671230a9aa84f85649766527ceccaf30a80f2f72 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Sun, 29 May 2022 00:09:51 +0200
Subject: [PATCH] Streamline database tests

---
 .../scala/docspell/store/DatabaseTest.scala   | 83 +++++++++++++++++++
 .../docspell/store/{migrate => }/Docker.scala |  7 +-
 .../scala/docspell/store/StoreFixture.scala   |  4 +-
 .../store/migrate/H2MigrateTest.scala         | 49 -----------
 .../store/migrate/MariaDbMigrateTest.scala    | 42 ----------
 .../docspell/store/migrate/MigrateTest.scala  | 73 ++++++++++++++++
 .../store/migrate/PostgresqlMigrateTest.scala | 45 ----------
 7 files changed, 160 insertions(+), 143 deletions(-)
 create mode 100644 modules/store/src/test/scala/docspell/store/DatabaseTest.scala
 rename modules/store/src/test/scala/docspell/store/{migrate => }/Docker.scala (69%)
 delete mode 100644 modules/store/src/test/scala/docspell/store/migrate/H2MigrateTest.scala
 delete mode 100644 modules/store/src/test/scala/docspell/store/migrate/MariaDbMigrateTest.scala
 create mode 100644 modules/store/src/test/scala/docspell/store/migrate/MigrateTest.scala
 delete mode 100644 modules/store/src/test/scala/docspell/store/migrate/PostgresqlMigrateTest.scala

diff --git a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
new file mode 100644
index 00000000..d4180b66
--- /dev/null
+++ b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
@@ -0,0 +1,83 @@
+package docspell.store
+
+import cats.effect._
+import com.dimafeng.testcontainers.{
+  JdbcDatabaseContainer,
+  MariaDBContainer,
+  PostgreSQLContainer
+}
+import com.dimafeng.testcontainers.munit.fixtures.TestContainersFixtures
+import docspell.common._
+import docspell.logging.TestLoggingConfig
+import munit.CatsEffectSuite
+import org.testcontainers.utility.DockerImageName
+
+import java.util.UUID
+
+trait DatabaseTest
+    extends CatsEffectSuite
+    with TestContainersFixtures
+    with TestLoggingConfig {
+
+  lazy val mariadbCnt = ForAllContainerFixture(
+    MariaDBContainer.Def(DockerImageName.parse("mariadb:10.5")).createContainer()
+  )
+
+  lazy val postgresCnt = ForAllContainerFixture(
+    PostgreSQLContainer.Def(DockerImageName.parse("postgres:14")).createContainer()
+  )
+
+  lazy val pgDataSource = ResourceSuiteLocalFixture(
+    "pgDataSource",
+    DatabaseTest.makeDataSourceFixture(postgresCnt())
+  )
+
+  lazy val mariaDataSource = ResourceSuiteLocalFixture(
+    "mariaDataSource",
+    DatabaseTest.makeDataSourceFixture(mariadbCnt())
+  )
+
+  lazy val h2DataSource = ResourceSuiteLocalFixture(
+    "h2DataSource", {
+      val jdbc = StoreFixture.memoryDB("test")
+      StoreFixture.dataSource(jdbc).map(ds => (jdbc, ds))
+    }
+  )
+
+  lazy val newH2DataSource = ResourceFixture(for {
+    jdbc <- Resource.eval(IO(StoreFixture.memoryDB(UUID.randomUUID().toString)))
+    ds <- StoreFixture.dataSource(jdbc)
+  } yield (jdbc, ds))
+
+  lazy val pgStore = ResourceSuiteLocalFixture(
+    "pgStore", {
+      val (jdbc, ds) = pgDataSource()
+      StoreFixture.store(ds, jdbc)
+    }
+  )
+
+  lazy val mariaStore = ResourceSuiteLocalFixture(
+    "mariaStore", {
+      val (jdbc, ds) = mariaDataSource()
+      StoreFixture.store(ds, jdbc)
+    }
+  )
+
+  lazy val h2Store = ResourceSuiteLocalFixture(
+    "h2Store", {
+      val (jdbc, ds) = h2DataSource()
+      StoreFixture.store(ds, jdbc)
+    }
+  )
+}
+
+object DatabaseTest {
+  private def jdbcConfig(cnt: JdbcDatabaseContainer) =
+    JdbcConfig(LenientUri.unsafe(cnt.jdbcUrl), cnt.username, cnt.password)
+
+  private def makeDataSourceFixture(cnt: JdbcDatabaseContainer) =
+    for {
+      jdbc <- Resource.eval(IO(jdbcConfig(cnt)))
+      ds <- StoreFixture.dataSource(jdbc)
+    } yield (jdbc, ds)
+}
diff --git a/modules/store/src/test/scala/docspell/store/migrate/Docker.scala b/modules/store/src/test/scala/docspell/store/Docker.scala
similarity index 69%
rename from modules/store/src/test/scala/docspell/store/migrate/Docker.scala
rename to modules/store/src/test/scala/docspell/store/Docker.scala
index 29763623..e18da006 100644
--- a/modules/store/src/test/scala/docspell/store/migrate/Docker.scala
+++ b/modules/store/src/test/scala/docspell/store/Docker.scala
@@ -1,10 +1,5 @@
-/*
- * Copyright 2020 Eike K. & Contributors
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
+package docspell.store
 
-package docspell.store.migrate
 import cats.effect._
 import cats.effect.unsafe.implicits._
 
diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
index 04583fed..d90b8d93 100644
--- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala
+++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
@@ -90,8 +90,10 @@ object StoreFixture {
     } yield xa
 
   def store(jdbc: JdbcConfig): Resource[IO, StoreImpl[IO]] =
+    dataSource(jdbc).flatMap(store(_, jdbc))
+
+  def store(ds: DataSource, jdbc: JdbcConfig): Resource[IO, StoreImpl[IO]] =
     for {
-      ds <- dataSource(jdbc)
       xa <- makeXA(ds)
       cfg = FileRepositoryConfig.Database(64 * 1024)
       fr = FileRepository[IO](xa, ds, cfg, true)
diff --git a/modules/store/src/test/scala/docspell/store/migrate/H2MigrateTest.scala b/modules/store/src/test/scala/docspell/store/migrate/H2MigrateTest.scala
deleted file mode 100644
index cb51023a..00000000
--- a/modules/store/src/test/scala/docspell/store/migrate/H2MigrateTest.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2020 Eike K. & Contributors
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-package docspell.store.migrate
-
-import cats.effect.IO
-import cats.effect.unsafe.implicits._
-
-import docspell.logging.TestLoggingConfig
-import docspell.store.{SchemaMigrateConfig, StoreFixture}
-
-import munit.FunSuite
-
-class H2MigrateTest extends FunSuite with TestLoggingConfig {
-
-  test("h2 empty schema migration") {
-    val jdbc = StoreFixture.memoryDB("h2test")
-    val ds = StoreFixture.dataSource(jdbc)
-    val result =
-      ds.flatMap(StoreFixture.makeXA).use { xa =>
-        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
-      }
-
-    assert(result.unsafeRunSync().migrationsExecuted > 0)
-
-    // a second time to apply fixup migrations
-    assert(result.unsafeRunSync().migrationsExecuted == 0)
-  }
-
-  test("h2 upgrade db from 0.24.0") {
-    val dump = "/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql"
-
-    val jdbc = StoreFixture.memoryDB("h2test2")
-    val ds = StoreFixture.dataSource(jdbc)
-
-    ds.use(StoreFixture.restoreH2Dump(dump, _)).unsafeRunSync()
-
-    val result =
-      ds.flatMap(StoreFixture.makeXA).use { xa =>
-        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
-      }
-
-    result.unsafeRunSync()
-    result.unsafeRunSync()
-  }
-}
diff --git a/modules/store/src/test/scala/docspell/store/migrate/MariaDbMigrateTest.scala b/modules/store/src/test/scala/docspell/store/migrate/MariaDbMigrateTest.scala
deleted file mode 100644
index 75e765b6..00000000
--- a/modules/store/src/test/scala/docspell/store/migrate/MariaDbMigrateTest.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2020 Eike K. & Contributors
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-package docspell.store.migrate
-
-import cats.effect._
-import cats.effect.unsafe.implicits._
-
-import docspell.common.LenientUri
-import docspell.logging.TestLoggingConfig
-import docspell.store.{JdbcConfig, SchemaMigrateConfig, StoreFixture}
-
-import com.dimafeng.testcontainers.MariaDBContainer
-import com.dimafeng.testcontainers.munit.TestContainerForAll
-import munit._
-import org.testcontainers.utility.DockerImageName
-
-class MariaDbMigrateTest
-    extends FunSuite
-    with TestContainerForAll
-    with TestLoggingConfig {
-  override val containerDef: MariaDBContainer.Def =
-    MariaDBContainer.Def(DockerImageName.parse("mariadb:10.5"))
-
-  test("mariadb empty schema migration") {
-    assume(Docker.existsUnsafe, "docker doesn't exist!")
-    withContainers { cnt =>
-      val jdbc =
-        JdbcConfig(LenientUri.unsafe(cnt.jdbcUrl), cnt.dbUsername, cnt.dbPassword)
-      val ds = StoreFixture.dataSource(jdbc)
-      val result = ds.flatMap(StoreFixture.makeXA).use { xa =>
-        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
-      }
-      assert(result.unsafeRunSync().migrationsExecuted > 0)
-      // a second time to apply fixup migrations
-      assert(result.unsafeRunSync().migrationsExecuted == 0)
-    }
-  }
-}
diff --git a/modules/store/src/test/scala/docspell/store/migrate/MigrateTest.scala b/modules/store/src/test/scala/docspell/store/migrate/MigrateTest.scala
new file mode 100644
index 00000000..0594578a
--- /dev/null
+++ b/modules/store/src/test/scala/docspell/store/migrate/MigrateTest.scala
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020 Eike K. & Contributors
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+package docspell.store.migrate
+
+import cats.effect._
+import docspell.store.{DatabaseTest, SchemaMigrateConfig, StoreFixture}
+import org.flywaydb.core.api.output.MigrateResult
+
+class MigrateTest extends DatabaseTest {
+
+  // don't register store-Fixture as this would run the migrations already
+  override def munitFixtures =
+    List(postgresCnt, mariadbCnt, pgDataSource, mariaDataSource, h2DataSource)
+
+  test("postgres empty schema migration") {
+    val (jdbc, ds) = pgDataSource()
+    val result =
+      StoreFixture.makeXA(ds).use { xa =>
+        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
+      }
+
+    assertMigrationResult(result)
+  }
+
+  test("mariadb empty schema migration") {
+    val (jdbc, ds) = mariaDataSource()
+    val result =
+      StoreFixture.makeXA(ds).use { xa =>
+        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
+      }
+
+    assertMigrationResult(result)
+  }
+
+  test("h2 empty schema migration") {
+    val (jdbc, ds) = h2DataSource()
+    val result =
+      StoreFixture.makeXA(ds).use { xa =>
+        FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
+      }
+
+    assertMigrationResult(result)
+  }
+
+  newH2DataSource.test("h2 upgrade db from 0.24.0") { case (jdbc, ds) =>
+    val dump = "/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql"
+    for {
+      _ <- StoreFixture.restoreH2Dump(dump, ds)
+
+      result =
+        StoreFixture.makeXA(ds).use { xa =>
+          FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
+        }
+
+      _ <- result
+      _ <- result
+    } yield ()
+  }
+
+  def assertMigrationResult(migrate: IO[MigrateResult]) =
+    for {
+      r1 <- migrate.map(_.migrationsExecuted)
+      // a second time to apply fixup migrations
+      r2 <- migrate.map(_.migrationsExecuted)
+    } yield {
+      assert(r1 > 0)
+      assertEquals(r2, 0)
+    }
+}
diff --git a/modules/store/src/test/scala/docspell/store/migrate/PostgresqlMigrateTest.scala b/modules/store/src/test/scala/docspell/store/migrate/PostgresqlMigrateTest.scala
deleted file mode 100644
index f71d01c8..00000000
--- a/modules/store/src/test/scala/docspell/store/migrate/PostgresqlMigrateTest.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2020 Eike K. & Contributors
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-package docspell.store.migrate
-
-import cats.effect._
-import cats.effect.unsafe.implicits._
-
-import docspell.common.LenientUri
-import docspell.logging.TestLoggingConfig
-import docspell.store.{JdbcConfig, SchemaMigrateConfig, StoreFixture}
-
-import com.dimafeng.testcontainers.PostgreSQLContainer
-import com.dimafeng.testcontainers.munit.TestContainerForAll
-import munit._
-import org.testcontainers.utility.DockerImageName
-
-class PostgresqlMigrateTest
-    extends FunSuite
-    with TestContainerForAll
-    with TestLoggingConfig {
-  override val containerDef: PostgreSQLContainer.Def =
-    PostgreSQLContainer.Def(DockerImageName.parse("postgres:14"))
-
-  test("postgres empty schema migration") {
-    assume(Docker.existsUnsafe, "docker doesn't exist!")
-    withContainers { cnt =>
-      val jdbc =
-        JdbcConfig(LenientUri.unsafe(cnt.jdbcUrl), cnt.username, cnt.password)
-
-      val ds = StoreFixture.dataSource(jdbc)
-      val result =
-        ds.flatMap(StoreFixture.makeXA).use { xa =>
-          FlywayMigrate[IO](jdbc, SchemaMigrateConfig.defaults, xa).run
-        }
-      assert(result.unsafeRunSync().migrationsExecuted > 0)
-
-      // a second time to apply fixup migrations
-      assert(result.unsafeRunSync().migrationsExecuted == 0)
-    }
-  }
-}