Repository: BlueBrain/nexus (scala)

Issue:
Database name is not respected
**Describe the bug**

When running nexus, I might have a configuration that looks like this
```
app {
  defaults {
    database {
      name = "db_name"
      username = "db_username"
    }
  }
}
```
The expectation is that delta would connect to a database named `db_name`

What actually happens is that delta connects to a database named `db_username`

This is due to delta using an incorrect jdbc string:
`jdbc:postgresql://${host}:${port}/`
When specified like this, jdbc uses the username as the database name as a default.

The correct specification would be 
`jdbc:postgresql://${host}:${port}/${db_name}`

**What part of Nexus is affected**
- [ ] Fusion
- [x] Delta
- [ ] CLI
- [ ] Documentation

Pull request:
Fixes #3886 

Thought it better to be explicit in the tests too? (i.e. now you can change that value and it won't break any tests)

Patch:
diff --git a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/Transactors.scala b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/Transactors.scala
index 110a08df7f..90f6ed6c2c 100644
--- a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/Transactors.scala
+++ b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/Transactors.scala
@@ -85,13 +85,13 @@ object Transactors {
     * @param password
     *   the password
     */
-  def test(host: String, port: Int, username: String, password: String): Resource[IO, Transactors] = {
+  def test(host: String, port: Int, username: String, password: String, database: String): Resource[IO, Transactors] = {
     val access         = DatabaseAccess(host, port, 10)
     val databaseConfig = DatabaseConfig(
       access,
       access,
       access,
-      "unused",
+      database,
       username,
       Secret(password),
       tablesAutocreate = false,
@@ -108,7 +108,7 @@ object Transactors {
         ec         <- ExecutionContexts.fixedThreadPool[IO](access.poolSize)
         dataSource <- Resource.make[IO, HikariDataSource](IO.delay {
                         val ds = new HikariDataSource
-                        ds.setJdbcUrl(s"jdbc:postgresql://${access.host}:${access.port}/")
+                        ds.setJdbcUrl(s"jdbc:postgresql://${access.host}:${access.port}/${config.name}")
                         ds.setUsername(config.username)
                         ds.setPassword(config.password.value)
                         ds.setDriverClassName("org.postgresql.Driver")


Test patch:
diff --git a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/MainSuite.scala b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/MainSuite.scala
index 7aadcbac6b..9876e71404 100644
--- a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/MainSuite.scala
+++ b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/MainSuite.scala
@@ -4,7 +4,7 @@ import akka.http.scaladsl.server.Route
 import cats.effect.IO
 import ch.epfl.bluebrain.nexus.delta.plugin.PluginsLoader.PluginLoaderConfig
 import ch.epfl.bluebrain.nexus.delta.sdk.plugin.PluginDef
-import ch.epfl.bluebrain.nexus.delta.sourcing.postgres.Doobie._
+import ch.epfl.bluebrain.nexus.delta.sourcing.postgres.{PostgresDb, PostgresPassword, PostgresUser}
 import ch.epfl.bluebrain.nexus.delta.wiring.DeltaModule
 import ch.epfl.bluebrain.nexus.testkit.config.SystemPropertyOverride
 import ch.epfl.bluebrain.nexus.testkit.mu.NexusSuite
@@ -105,7 +105,7 @@ object MainSuite {
     // Start the necessary containers
     private def resource() =
       for {
-        postgres <- PostgresContainer.resource(PostgresUser, PostgresPassword)
+        postgres <- PostgresContainer.resource(PostgresUser, PostgresPassword, PostgresDb)
         _        <- SystemPropertyOverride(initConfig(postgres))
       } yield ()
 
diff --git a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/Doobie.scala b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/Doobie.scala
index bd2b458c3f..9b37a16f7e 100644
--- a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/Doobie.scala
+++ b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/Doobie.scala
@@ -15,30 +15,21 @@ import munit.catseffect.ResourceFixture.FixtureNotInstantiatedException
 import org.postgresql.util.PSQLException
 
 object Doobie {
-
-  val PostgresUser     = "postgres"
-  val PostgresPassword = "postgres"
-
-  def transactors(
-      postgres: Resource[IO, PostgresContainer],
-      user: String,
-      pass: String
-  ): Resource[IO, Transactors] = {
-    postgres
-      .flatMap(container => Transactors.test(container.getHost, container.getMappedPort(5432), user, pass))
-      .evalTap(xas => Transactors.dropAndCreateDDLs.flatMap(xas.execDDLs))
+  def resource(): Resource[IO, Transactors] = {
+    val user     = PostgresUser
+    val pass     = PostgresPassword
+    val database = PostgresDb
+    for {
+      postgres    <- PostgresContainer.resource(user, pass, database)
+      transactors <- Transactors.test(postgres.getHost, postgres.getMappedPort(5432), user, pass, database)
+      _           <- Resource.eval(Transactors.dropAndCreateDDLs.flatMap(transactors.execDDLs))
+    } yield transactors
   }
 
-  def resource(
-      user: String = PostgresUser,
-      pass: String = PostgresPassword
-  ): Resource[IO, Transactors] =
-    transactors(PostgresContainer.resource(user, pass), user, pass)
-
   trait Fixture { self: NexusSuite =>
 
     val doobie: IOFixture[Transactors] =
-      ResourceSuiteLocalFixture("doobie", resource(PostgresUser, PostgresPassword))
+      ResourceSuiteLocalFixture("doobie", resource())
 
     /**
       * Truncate all tables after each test
@@ -53,7 +44,7 @@ object Doobie {
 
       def xas: Transactors = apply()
 
-      override def beforeAll(): IO[Unit] = resource(PostgresUser, PostgresPassword).allocated.flatMap { value =>
+      override def beforeAll(): IO[Unit] = resource().allocated.flatMap { value =>
         IO(this.value = Some(value))
       }
 
diff --git a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/DoobieScalaTestFixture.scala b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/DoobieScalaTestFixture.scala
index 25112e766b..8a03380813 100644
--- a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/DoobieScalaTestFixture.scala
+++ b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/DoobieScalaTestFixture.scala
@@ -21,7 +21,8 @@ trait DoobieScalaTestFixture
 
   override def beforeAll(): Unit = {
     super.beforeAll()
-    val xasResource = Transactors.test(container.getHost, container.getMappedPort(5432), "postgres", "postgres")
+    val xasResource =
+      Transactors.test(container.getHost, container.getMappedPort(5432), "postgres", "postgres", "postgres")
     val (x, t)      = xasResource.allocated.flatTap { case (x, _) =>
       Transactors.dropAndCreateDDLs.flatMap(x.execDDLs)
     }.accepted
diff --git a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/PostgresDocker.scala b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/PostgresDocker.scala
index 674f8026dd..fedc0e35ed 100644
--- a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/PostgresDocker.scala
+++ b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/PostgresDocker.scala
@@ -10,7 +10,7 @@ import scala.jdk.DurationConverters._
 trait PostgresDocker extends BeforeAndAfterAll { this: Suite =>
 
   protected val container: PostgresContainer =
-    new PostgresContainer(PostgresUser, PostgresPassword)
+    new PostgresContainer(PostgresUser, PostgresPassword, PostgresDb)
       .withReuse(false)
       .withStartupTimeout(60.seconds.toJava)
 
@@ -30,8 +30,5 @@ trait PostgresDocker extends BeforeAndAfterAll { this: Suite =>
 }
 
 object PostgresDocker {
-  val PostgresUser     = "postgres"
-  val PostgresPassword = "postgres"
-
   final case class PostgresHostConfig(host: String, port: Int)
 }
diff --git a/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/package.scala b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/package.scala
new file mode 100644
index 0000000000..3893209582
--- /dev/null
+++ b/delta/sourcing-psql/src/test/scala/ch/epfl/bluebrain/nexus/delta/sourcing/postgres/package.scala
@@ -0,0 +1,7 @@
+package ch.epfl.bluebrain.nexus.delta.sourcing
+
+package object postgres {
+  val PostgresUser     = "postgres"
+  val PostgresPassword = "postgres"
+  val PostgresDb       = "postgres"
+}
diff --git a/delta/testkit/src/main/scala/ch/epfl/bluebrain/nexus/testkit/postgres/PostgresContainer.scala b/delta/testkit/src/main/scala/ch/epfl/bluebrain/nexus/testkit/postgres/PostgresContainer.scala
index 286dc4d19d..07d40b572f 100644
--- a/delta/testkit/src/main/scala/ch/epfl/bluebrain/nexus/testkit/postgres/PostgresContainer.scala
+++ b/delta/testkit/src/main/scala/ch/epfl/bluebrain/nexus/testkit/postgres/PostgresContainer.scala
@@ -8,10 +8,11 @@ import org.testcontainers.utility.DockerImageName
 import scala.concurrent.duration.DurationInt
 import scala.jdk.DurationConverters.ScalaDurationOps
 
-class PostgresContainer(user: String, password: String)
+class PostgresContainer(user: String, password: String, database: String)
     extends GenericContainer[PostgresContainer](DockerImageName.parse("library/postgres:15.6")) {
   addEnv("POSTGRES_USER", user)
   addEnv("POSTGRES_PASSWORD", password)
+  addEnv("POSTGRES_DB222", database)
   addExposedPort(5432)
   setWaitStrategy(Wait.forLogMessage(".*database system is ready to accept connections.*\\s", 2))
   setCommand("postgres", "-c", "fsync=off")
@@ -21,14 +22,10 @@ object PostgresContainer {
 
   /**
     * A running postgres container wrapped in a Resource. The container will be stopped upon release.
-    * @param user
-    *   the db username
-    * @param password
-    *   the db password
     */
-  def resource(user: String, password: String): Resource[IO, PostgresContainer] = {
+  def resource(user: String, password: String, database: String): Resource[IO, PostgresContainer] = {
     def createAndStartContainer = IO.blocking {
-      val container = new PostgresContainer(user, password)
+      val container = new PostgresContainer(user, password, database)
         .withReuse(false)
         .withStartupTimeout(60.seconds.toJava)
       container.start()