Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rolang committed Dec 1, 2024
1 parent 9298381 commit 5985773
Show file tree
Hide file tree
Showing 17 changed files with 78 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ private[dumbo] trait DumboPlatform {
val (locationInfo, resources) = ResourceFilePath.fromResourcesDir(location)

new DumboWithResourcesPartiallyApplied[F](
ResourceReader.embeddedResources(resources, Some(locationInfo))
ResourceReader.embeddedResources(
readResources = resources,
locationInfo = Some(locationInfo),
locationRelative = Some(location),
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import dumbo.{DumboWithResourcesPartiallyApplied, ResourceFilePath}
private[dumbo] trait DumboPlatform {
inline def withResourcesIn[F[_]: Sync](location: String): DumboWithResourcesPartiallyApplied[F] = {
val resources = ResourceFilePath.fromResourcesDir(location)
new DumboWithResourcesPartiallyApplied[F](ResourceReader.embeddedResources(Sync[F].pure(resources)))
new DumboWithResourcesPartiallyApplied[F](
ResourceReader.embeddedResources(
readResources = Sync[F].pure(resources),
locationInfo = Some(location),
locationRelative = Some(location),
)
)
}
}
12 changes: 9 additions & 3 deletions modules/core/shared/src/main/scala/dumbo/Dumbo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,19 @@ class Dumbo[F[_]: Sync: Console](
version = source.versionText,
description = source.scriptDescription,
`type` = "SQL",
script = source.path.fileName,
script = historyScriptPath(source),
checksum = Some(source.checksum),
executionTimeMs = duration.toMillis.toInt,
success = true,
)
}

private def historyScriptPath(resource: ResourceFile) =
resReader.locationRel match {
case Some(loc) => resource.path.value.stripPrefix(s"/$loc/")
case _ => resource.fileName
}

private def validationGuard(session: Session[F], resources: ResourceFiles) =
if (resources.nonEmpty) {
session
Expand Down Expand Up @@ -446,13 +452,13 @@ class Dumbo[F[_]: Sync: Console](
resources: ResourceFiles,
): ValidatedNec[DumboValidationException, Unit] = {
val versionedMap: Map[String, ResourceFile] = resources.versioned.map { case (v, f) => (v.text, f) }.toMap
val repeatablesFileNames: Set[String] = resources.repeatable.map(_._2.fileName).toSet
val repeatablesScriptNames: Set[String] = resources.repeatable.map(_._2.path.value).toSet

history
.filter(_.`type` == "SQL")
.traverse { h =>
versionedMap.get(h.version.getOrElse("")) match {
case None if !repeatablesFileNames.contains(h.script) =>
case None if !repeatablesScriptNames.exists(_.endsWith(h.script)) =>
new DumboValidationException(s"Detected applied migration not resolved locally ${h.script}")
.invalidNec[Unit]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@

package dumbo.internal

import java.io.File

import cats.effect.Sync
import cats.implicits.*
import dumbo.ResourceFilePath
import fs2.io.file.{Files as Fs2Files, Flags, Path}
import fs2.{Stream, text}

private[dumbo] trait ResourceReader[F[_]] {
// relative location info e.g. "db/migration"
def locationRel: Option[String]

// relative or absolute location info e.g. "file:/project/resources/db/migration"
def location: Option[String]

def list: fs2.Stream[F, ResourceFilePath]
Expand All @@ -28,12 +34,22 @@ private[dumbo] object ResourceReader {

@inline def absolutePath(p: Path) = if (p.isAbsolute) p else base / p

@scala.annotation.tailrec
def listRec(dirs: List[File], files: List[File]): List[File] =
dirs match {
case x :: xs =>
val (d, f) = x.listFiles().toList.partition(_.isDirectory())
listRec(d ::: xs, f ::: files)
case Nil => files
}

new ResourceReader[F] {
override val location: Option[String] = Some(absolutePath(sourceDir).toString)
override val locationRel: Option[String] = Some(sourceDir.toString)
override val location: Option[String] = Some(absolutePath(sourceDir).toString)
override def list: Stream[F, ResourceFilePath] =
Fs2Files[F]
.list(absolutePath(sourceDir))
.map(p => ResourceFilePath(p.toString))
Stream.emits(
listRec(List(new File(absolutePath(sourceDir).toString)), Nil).map(f => ResourceFilePath(f.getPath()))
)

override def readUtf8Lines(path: ResourceFilePath): Stream[F, String] =
Fs2Files[F].readUtf8Lines(absolutePath(Path(path.value)))
Expand All @@ -48,8 +64,11 @@ private[dumbo] object ResourceReader {
def embeddedResources[F[_]: Sync](
readResources: F[List[ResourceFilePath]],
locationInfo: Option[String] = None,
locationRelative: Option[String] = None,
): ResourceReader[F] =
new ResourceReader[F] {
override val locationRel: Option[String] = locationRelative

override val location: Option[String] = locationInfo

override def list: Stream[F, ResourceFilePath] = Stream.evals(readResources)
Expand Down
13 changes: 13 additions & 0 deletions modules/tests-flyway/src/test/scala/DumboFlywaySpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@ trait DumboFlywaySpec extends ffstest.FTest {
} yield ()
}

dbTest("Compatible with nested directories") {
val schema = "schema_1"

for {
_ <- flywayMigrate(schema, Path("db/nested")).map(r => assert(r.migrationsExecuted == 6))
historyFlyway <- loadHistory(schema)
_ <- dropSchemas
_ <- dumboMigrate(schema, dumboWithResources("db/nested")).map(r => assert(r.migrationsExecuted == 6))
historyDumbo <- loadHistory(schema)
_ = assertEqualHistory(historyDumbo, historyFlyway)
} yield ()
}

dbTest("Dumbo updates history entry of latest unsucessfully applied migration by Flyway") {
// run on CockroachDb only just because it was the easiest way to reproduce a history record for an unsuccessfully applied migration with Flyway
if (db == Db.CockroachDb) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test (id SERIAL PRIMARY KEY);
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_a();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_b();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_f();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_d();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_e();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE TABLE test_c();
17 changes: 14 additions & 3 deletions modules/tests/shared/src/test/scala/DumboResourcesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class DumboResourcesSpec extends ffstest.FTest {
(ResourceVersion.Versioned("2", NonEmptyList.of(2)), "V2__test.sql"),
(ResourceVersion.Versioned("3", NonEmptyList.of(3)), "V3__test.sql"),
(ResourceVersion.Versioned("4", NonEmptyList.of(4)), "V4__test.sql"),
(ResourceVersion.Versioned("5", NonEmptyList.of(5)), "V5__test.sql"),
(ResourceVersion.Repeatable("a"), "R__a.sql"),
(ResourceVersion.Repeatable("b"), "R__b.sql"),
)
)
case Invalid(errs) => fail(errs.toList.mkString("\n"))
Expand All @@ -55,7 +56,12 @@ class DumboResourcesSpec extends ffstest.FTest {
case Valid(files) =>
assert(
files.sorted.map(f => (f.version, f.path.fileName.toString)) == List(
(ResourceVersion.Versioned("1", NonEmptyList.of(1)), "V1__non_resource.sql")
(ResourceVersion.Versioned("1", NonEmptyList.of(1)), "V1__non_resource.sql"),
(ResourceVersion.Versioned("2", NonEmptyList.of(2)), "V2__non_resource.sql"),
(ResourceVersion.Versioned("3", NonEmptyList.of(3)), "V3__non_resource.sql"),
(ResourceVersion.Versioned("4", NonEmptyList.of(4)), "V4__non_resource.sql"),
(ResourceVersion.Repeatable("a"), "R__a.sql"),
(ResourceVersion.Repeatable("b"), "R__b.sql"),
)
)
case Invalid(errs) => fail(errs.toList.mkString("\n"))
Expand All @@ -71,7 +77,12 @@ class DumboResourcesSpec extends ffstest.FTest {
case Valid(files) =>
assert(
files.sorted.map(f => (f.version, f.path.fileName.toString)) == List(
(ResourceVersion.Versioned("1", NonEmptyList.of(1)), "V1__non_resource.sql")
(ResourceVersion.Versioned("1", NonEmptyList.of(1)), "V1__non_resource.sql"),
(ResourceVersion.Versioned("2", NonEmptyList.of(2)), "V2__non_resource.sql"),
(ResourceVersion.Versioned("3", NonEmptyList.of(3)), "V3__non_resource.sql"),
(ResourceVersion.Versioned("4", NonEmptyList.of(4)), "V4__non_resource.sql"),
(ResourceVersion.Repeatable("a"), "R__a.sql"),
(ResourceVersion.Repeatable("b"), "R__b.sql"),
)
)
case Invalid(errs) => fail(errs.toList.mkString("\n"))
Expand Down

0 comments on commit 5985773

Please sign in to comment.