From 05a89e1a7301047c4b77a2eadfbbc3e9256a7923 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Fri, 14 Jun 2019 18:10:36 +0200 Subject: [PATCH] Default to file based databases in tests (#517) This is due to issues with deadlocks with in-memory based databases. We need DBs to stay alive between connections, but not across tests. In DB intensive chain validation tests we use in-memory databases instead. This seems like a reasonable tradeoff between simplicity and speed. --- .../chain/blockchain/ChainHandlerTest.scala | 9 ++- .../bitcoins/chain/pow/BitcoinPowTest.scala | 7 ++- .../chain/validation/TipValidationTest.scala | 1 + .../bitcoins/testkit/BitcoinSAppConfig.scala | 58 +++++++++++++------ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/chain-test/src/test/scala/org/bitcoins/chain/blockchain/ChainHandlerTest.scala b/chain-test/src/test/scala/org/bitcoins/chain/blockchain/ChainHandlerTest.scala index 99b7580a5f..714fd87c6b 100644 --- a/chain-test/src/test/scala/org/bitcoins/chain/blockchain/ChainHandlerTest.scala +++ b/chain-test/src/test/scala/org/bitcoins/chain/blockchain/ChainHandlerTest.scala @@ -15,15 +15,20 @@ import org.scalatest.{Assertion, FutureOutcome} import play.api.libs.json.Json import scala.concurrent.Future +import org.bitcoins.testkit.BitcoinSAppConfig class ChainHandlerTest extends ChainUnitTest { override type FixtureParam = ChainHandler - override implicit val system = ActorSystem("ChainUnitTest") + implicit override val system = ActorSystem("ChainUnitTest") // we're working with mainnet data - override lazy implicit val appConfig: ChainAppConfig = mainnetAppConfig + implicit override lazy val appConfig: ChainAppConfig = { + val memoryDb = BitcoinSAppConfig.configWithMemoryDb( + Some(BitcoinSAppConfig.ProjectType.Chain)) + mainnetAppConfig.withOverrides(memoryDb) + } override val defaultTag: ChainFixtureTag = ChainFixtureTag.GenisisChainHandler diff --git a/chain-test/src/test/scala/org/bitcoins/chain/pow/BitcoinPowTest.scala b/chain-test/src/test/scala/org/bitcoins/chain/pow/BitcoinPowTest.scala index 0e6da4e9bd..25d86d3b09 100644 --- a/chain-test/src/test/scala/org/bitcoins/chain/pow/BitcoinPowTest.scala +++ b/chain-test/src/test/scala/org/bitcoins/chain/pow/BitcoinPowTest.scala @@ -9,12 +9,17 @@ import org.bitcoins.testkit.chain.{ChainTestUtil, ChainUnitTest} import org.scalatest.FutureOutcome import scala.concurrent.Future +import org.bitcoins.testkit.BitcoinSAppConfig class BitcoinPowTest extends ChainUnitTest { override type FixtureParam = ChainFixture - implicit override lazy val appConfig: ChainAppConfig = mainnetAppConfig + implicit override lazy val appConfig: ChainAppConfig = { + val memoryDb = BitcoinSAppConfig.configWithMemoryDb( + Some(BitcoinSAppConfig.ProjectType.Chain)) + mainnetAppConfig.withOverrides(memoryDb) + } override def withFixture(test: OneArgAsyncTest): FutureOutcome = withChainFixture(test) diff --git a/chain-test/src/test/scala/org/bitcoins/chain/validation/TipValidationTest.scala b/chain-test/src/test/scala/org/bitcoins/chain/validation/TipValidationTest.scala index bdf0d07089..34718f3ddc 100644 --- a/chain-test/src/test/scala/org/bitcoins/chain/validation/TipValidationTest.scala +++ b/chain-test/src/test/scala/org/bitcoins/chain/validation/TipValidationTest.scala @@ -18,6 +18,7 @@ import org.scalatest.{Assertion, FutureOutcome} import scala.concurrent.Future import org.bitcoins.chain.config.ChainAppConfig import com.typesafe.config.ConfigFactory +import org.bitcoins.testkit.BitcoinSAppConfig class TipValidationTest extends ChainUnitTest { diff --git a/testkit/src/main/scala/org/bitcoins/testkit/BitcoinSAppConfig.scala b/testkit/src/main/scala/org/bitcoins/testkit/BitcoinSAppConfig.scala index bf555d8cae..b9a016061f 100644 --- a/testkit/src/main/scala/org/bitcoins/testkit/BitcoinSAppConfig.scala +++ b/testkit/src/main/scala/org/bitcoins/testkit/BitcoinSAppConfig.scala @@ -67,31 +67,14 @@ object BitcoinSAppConfig { /** * App configuration suitable for test purposes: - + * * 1) Data directory is set to user temp directory - * 2) All databases are in-memory */ def getTestConfig(config: Config*) = { val tmpDir = Files.createTempDirectory("bitcoin-s-") val confStr = s""" | bitcoin-s { | datadir = $tmpDir - | - | wallet.db { - | url = "jdbc:sqlite:file::memory:?cache=shared" - | connectionPool = disabled - | keepAliveConnection = true - | } - | node.db { - | url = "jdbc:sqlite:file::memory:?cache=shared" - | connectionPool = disabled - | keepAliveConnection = true - | } - | chain.db { - | url = "jdbc:sqlite:file::memory:?cache=shared" - | connectionPool = disabled - | keepAliveConnection = true - | } | } | |""".stripMargin @@ -100,4 +83,43 @@ object BitcoinSAppConfig { BitcoinSAppConfig(allConfs: _*) } + sealed trait ProjectType + + object ProjectType { + case object Wallet extends ProjectType + case object Node extends ProjectType + case object Chain extends ProjectType + + val all = List(Wallet, Node, Chain) + } + + /** Generates a Typesafe config with DBs set to memory + * databases for the given project (or all, if no + * project is given). This configuration can then be + * given as a override to other configs. + */ + def configWithMemoryDb(project: Option[ProjectType]): Config = { + def memConfigForProject(project: ProjectType): String = { + val name = project.toString().toLowerCase() + s""" + | $name.db { + | url = "jdbc:sqlite:file:$name.db:?mode=memory&cache=shared" + | connectionPool = disabled + | keepAliveConnection = true + | } + |""".stripMargin + } + + val confStr = project match { + case None => ProjectType.all.map(memConfigForProject).mkString("\n") + case Some(p) => memConfigForProject(p) + } + val nestedConfStr = s""" + | bitcoin-s { + | $confStr + | } + |""".stripMargin + ConfigFactory.parseString(nestedConfStr) + } + }