mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
Make tests to not require pre-installed bitcoind (#766)
* Make tests to not require pre-installed bitcoind * update docs
This commit is contained in:
parent
eefbc37a81
commit
7e19a706de
@ -1,25 +1,26 @@
|
||||
package org.bitcoins.rpc
|
||||
import java.io.{File, PrintWriter}
|
||||
import java.net.URI
|
||||
import java.nio.file.{Files, Path}
|
||||
|
||||
import akka.stream.StreamTcpException
|
||||
import org.bitcoins.core.config.RegTest
|
||||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.util.BitcoindRpcTest
|
||||
|
||||
import scala.io.Source
|
||||
import akka.stream.StreamTcpException
|
||||
import java.nio.file.Paths
|
||||
import scala.util.Properties
|
||||
import org.bitcoins.rpc.config.BitcoindConfig
|
||||
import org.bitcoins.rpc.config.BitcoindAuthCredentials
|
||||
import org.bitcoins.rpc.config.{
|
||||
BitcoindAuthCredentials,
|
||||
BitcoindConfig,
|
||||
BitcoindInstance
|
||||
}
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
import org.bitcoins.core.config.RegTest
|
||||
import java.net.URI
|
||||
import scala.concurrent.Future
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil.newestBitcoindBinary
|
||||
import org.bitcoins.testkit.util.BitcoindRpcTest
|
||||
import org.scalatest.compatible.Assertion
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.io.Source
|
||||
|
||||
class BitcoindInstanceTest extends BitcoindRpcTest {
|
||||
|
||||
private val sampleConf: Seq[String] = {
|
||||
@ -65,7 +66,7 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
||||
""".stripMargin
|
||||
|
||||
val conf = BitcoindConfig(confStr, BitcoindRpcTestUtil.tmpDir())
|
||||
val instance = BitcoindInstance.fromConfig(conf)
|
||||
val instance = BitcoindInstance.fromConfig(conf, newestBitcoindBinary)
|
||||
assert(
|
||||
instance.authCredentials
|
||||
.isInstanceOf[BitcoindAuthCredentials.CookieBased])
|
||||
@ -85,7 +86,7 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
||||
""".stripMargin
|
||||
|
||||
val conf = BitcoindConfig(confStr, BitcoindRpcTestUtil.tmpDir())
|
||||
val instance = BitcoindInstance.fromConfig(conf)
|
||||
val instance = BitcoindInstance.fromConfig(conf, newestBitcoindBinary)
|
||||
assert(
|
||||
instance.authCredentials
|
||||
.isInstanceOf[BitcoindAuthCredentials.PasswordBased])
|
||||
@ -121,14 +122,16 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
||||
uri = new URI(s"http://localhost:$port"),
|
||||
rpcUri = new URI(s"http://localhost:$rpcPort"),
|
||||
authCredentials = authCredentials,
|
||||
datadir = conf.datadir
|
||||
datadir = conf.datadir,
|
||||
binary = newestBitcoindBinary
|
||||
)
|
||||
|
||||
testClientStart(BitcoindRpcClient.withActorSystem(instance))
|
||||
}
|
||||
|
||||
it should "parse a bitcoin.conf file, start bitcoind, mine some blocks and quit" in {
|
||||
val instance = BitcoindInstance.fromDatadir(datadir.toFile)
|
||||
val instance =
|
||||
BitcoindInstance.fromDatadir(datadir.toFile, newestBitcoindBinary)
|
||||
val client = BitcoindRpcClient.withActorSystem(instance)
|
||||
|
||||
for {
|
||||
|
@ -4,7 +4,6 @@ import java.io.File
|
||||
|
||||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.common.RpcOpts.AddNodeArgument
|
||||
import org.bitcoins.rpc.util.AsyncUtil.RpcRetryException
|
||||
import org.bitcoins.rpc.util.{AsyncUtil, RpcUtil}
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
|
@ -2,7 +2,7 @@ package org.bitcoins.rpc.common
|
||||
|
||||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.client.common.RpcOpts.{AddNodeArgument, AddressType}
|
||||
import org.bitcoins.rpc.util.AsyncUtil
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
@ -14,13 +14,14 @@ import org.bitcoins.core.config.RegTest
|
||||
class BlockchainRpcTest extends BitcoindRpcTest {
|
||||
|
||||
lazy val clientsF: Future[(BitcoindRpcClient, BitcoindRpcClient)] =
|
||||
BitcoindRpcTestUtil.createNodePair(clientAccum = clientAccum)
|
||||
BitcoindRpcTestUtil.createNodePairV17(clientAccum = clientAccum)
|
||||
|
||||
lazy val pruneClientF: Future[BitcoindRpcClient] = clientsF.flatMap {
|
||||
case (_, _) =>
|
||||
val pruneClient =
|
||||
BitcoindRpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.instance(pruneMode = true))
|
||||
BitcoindRpcTestUtil.instance(pruneMode = true,
|
||||
versionOpt = Some(BitcoindVersion.V17)))
|
||||
|
||||
clientAccum += pruneClient
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
package org.bitcoins.rpc.common
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
import com.typesafe.config.ConfigValueFactory
|
||||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.core.protocol.script.ScriptSignature
|
||||
@ -17,11 +15,10 @@ import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.util.BitcoindRpcTest
|
||||
|
||||
import scala.concurrent.Future
|
||||
import java.nio.file.Path
|
||||
|
||||
class MempoolRpcTest extends BitcoindRpcTest {
|
||||
lazy val clientsF: Future[(BitcoindRpcClient, BitcoindRpcClient)] =
|
||||
BitcoindRpcTestUtil.createNodePair(clientAccum = clientAccum)
|
||||
BitcoindRpcTestUtil.createNodePairV18(clientAccum = clientAccum)
|
||||
|
||||
lazy val clientWithoutBroadcastF: Future[BitcoindRpcClient] =
|
||||
clientsF.flatMap {
|
||||
@ -33,7 +30,8 @@ class MempoolRpcTest extends BitcoindRpcTest {
|
||||
.withOption("walletbroadcast", 0.toString)
|
||||
|
||||
val instanceWithoutBroadcast =
|
||||
BitcoindInstance.fromConfig(configNoBroadcast)
|
||||
BitcoindInstance.fromConfig(configNoBroadcast,
|
||||
BitcoindRpcTestUtil.newestBitcoindBinary)
|
||||
|
||||
val clientWithoutBroadcast =
|
||||
BitcoindRpcClient.withActorSystem(instanceWithoutBroadcast)
|
||||
|
@ -9,7 +9,7 @@ import org.bitcoins.rpc.BitcoindP2PException.NotConnected
|
||||
|
||||
class MiningRpcTest extends BitcoindRpcTest {
|
||||
lazy val clientsF: Future[(BitcoindRpcClient, BitcoindRpcClient)] =
|
||||
BitcoindRpcTestUtil.createNodePair(clientAccum = clientAccum)
|
||||
BitcoindRpcTestUtil.createNodePairV17(clientAccum = clientAccum)
|
||||
|
||||
behavior of "MiningRpc"
|
||||
|
||||
|
@ -20,7 +20,7 @@ import org.bitcoins.rpc.BitcoindException.InvalidAddressOrKey
|
||||
|
||||
class RawTransactionRpcTest extends BitcoindRpcTest {
|
||||
lazy val clientsF: Future[(BitcoindRpcClient, BitcoindRpcClient)] =
|
||||
BitcoindRpcTestUtil.createNodePair(clientAccum = clientAccum)
|
||||
BitcoindRpcTestUtil.createNodePairV17(clientAccum = clientAccum)
|
||||
|
||||
behavior of "RawTransactionRpc"
|
||||
|
||||
|
@ -33,7 +33,7 @@ import scala.concurrent.Future
|
||||
class WalletRpcTest extends BitcoindRpcTest {
|
||||
lazy val clientsF: Future[
|
||||
(BitcoindRpcClient, BitcoindRpcClient, BitcoindRpcClient)] =
|
||||
BitcoindRpcTestUtil.createNodeTriple(clientAccum = clientAccum)
|
||||
BitcoindRpcTestUtil.createNodeTripleV17(clientAccum = clientAccum)
|
||||
|
||||
// This client's wallet is encrypted
|
||||
lazy val walletClientF: Future[BitcoindRpcClient] = clientsF.flatMap { _ =>
|
||||
|
@ -75,8 +75,9 @@ object BitcoindRpcClient {
|
||||
* the default datadir if no directory is provided
|
||||
*/
|
||||
def fromDatadir(
|
||||
datadir: File = BitcoindConfig.DEFAULT_DATADIR): BitcoindRpcClient = {
|
||||
val instance = BitcoindInstance.fromDatadir(datadir)
|
||||
datadir: File = BitcoindConfig.DEFAULT_DATADIR,
|
||||
binary: File): BitcoindRpcClient = {
|
||||
val instance = BitcoindInstance.fromDatadir(datadir, binary)
|
||||
val cli = BitcoindRpcClient(instance)
|
||||
cli
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.bitcoins.rpc.config
|
||||
|
||||
import java.io.File
|
||||
import java.io.{File, FileNotFoundException}
|
||||
import java.net.URI
|
||||
import java.nio.file.{Files, Paths}
|
||||
|
||||
@ -9,7 +9,6 @@ import org.bitcoins.core.util.BitcoinSLogger
|
||||
import org.bitcoins.rpc.client.common.BitcoindVersion
|
||||
|
||||
import scala.sys.process._
|
||||
|
||||
import org.bitcoins.core.util.BitcoinSLogger
|
||||
import org.bitcoins.core.config.NetworkParameters
|
||||
|
||||
@ -51,6 +50,9 @@ sealed trait BitcoindInstance extends BitcoinSLogger {
|
||||
.last
|
||||
|
||||
foundVersion match {
|
||||
case _: String
|
||||
if foundVersion.equals(BitcoindVersion.Experimental.toString) =>
|
||||
BitcoindVersion.Experimental
|
||||
case _: String if foundVersion.startsWith(BitcoindVersion.V16.toString) =>
|
||||
BitcoindVersion.V16
|
||||
case _: String if foundVersion.startsWith(BitcoindVersion.V17.toString) =>
|
||||
@ -95,16 +97,22 @@ object BitcoindInstance {
|
||||
|
||||
lazy val DEFAULT_BITCOIND_LOCATION: File = {
|
||||
|
||||
def findExecutableOnPath(name: String): Option[File] =
|
||||
sys.env
|
||||
.getOrElse("PATH", "")
|
||||
.split(File.pathSeparator)
|
||||
.map(directory => new File(directory, name))
|
||||
.find(file => file.isFile && file.canExecute)
|
||||
|
||||
val cmd =
|
||||
if (Properties.isWin) {
|
||||
"which bitcoind.exe".!!
|
||||
findExecutableOnPath("bitcoind.exe")
|
||||
} else {
|
||||
"which bitcoind".!!
|
||||
findExecutableOnPath("bitcoind")
|
||||
}
|
||||
|
||||
val path = cmd
|
||||
new File(path.trim)
|
||||
|
||||
cmd.getOrElse(
|
||||
throw new FileNotFoundException("Cannot find a path to bitcoind"))
|
||||
}
|
||||
|
||||
/** Constructs a `bitcoind` instance from the given datadir, using the
|
||||
@ -113,7 +121,9 @@ object BitcoindInstance {
|
||||
* @throws IllegalArgumentException if the given datadir does not exist
|
||||
*/
|
||||
def fromDatadir(
|
||||
datadir: File = BitcoindConfig.DEFAULT_DATADIR): BitcoindInstance = {
|
||||
datadir: File = BitcoindConfig.DEFAULT_DATADIR,
|
||||
binary: File = DEFAULT_BITCOIND_LOCATION
|
||||
): BitcoindInstance = {
|
||||
require(datadir.exists, s"${datadir.getPath} does not exist!")
|
||||
require(datadir.isDirectory, s"${datadir.getPath} is not a directory!")
|
||||
|
||||
@ -121,9 +131,9 @@ object BitcoindInstance {
|
||||
if (Files.exists(configPath)) {
|
||||
|
||||
val file = configPath.toFile()
|
||||
fromConfigFile(file)
|
||||
fromConfigFile(file, binary)
|
||||
} else {
|
||||
fromConfig(BitcoindConfig.empty)
|
||||
fromConfig(BitcoindConfig.empty, binary)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,18 +144,21 @@ object BitcoindInstance {
|
||||
* @throws IllegalArgumentException if the given config file does not exist
|
||||
*/
|
||||
def fromConfigFile(
|
||||
file: File = BitcoindConfig.DEFAULT_CONF_FILE): BitcoindInstance = {
|
||||
file: File = BitcoindConfig.DEFAULT_CONF_FILE,
|
||||
binary: File = DEFAULT_BITCOIND_LOCATION
|
||||
): BitcoindInstance = {
|
||||
require(file.exists, s"${file.getPath} does not exist!")
|
||||
require(file.isFile, s"${file.getPath} is not a file!")
|
||||
|
||||
val conf = BitcoindConfig(file, file.getParentFile)
|
||||
|
||||
fromConfig(conf)
|
||||
fromConfig(conf, binary)
|
||||
}
|
||||
|
||||
/** Constructs a `bitcoind` instance from the given config */
|
||||
def fromConfig(
|
||||
config: BitcoindConfig
|
||||
config: BitcoindConfig,
|
||||
binary: File = DEFAULT_BITCOIND_LOCATION
|
||||
): BitcoindInstance = {
|
||||
|
||||
val authCredentials = BitcoindAuthCredentials.fromConfig(config)
|
||||
@ -154,6 +167,7 @@ object BitcoindInstance {
|
||||
config.rpcUri,
|
||||
authCredentials,
|
||||
zmqConfig = ZmqConfig.fromConfig(config),
|
||||
binary = binary,
|
||||
datadir = config.datadir)
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,14 @@ import scala.concurrent._
|
||||
import org.bitcoins.{rpc, core}
|
||||
import core.currency.Bitcoins
|
||||
import rpc.client.common._
|
||||
import java.io._
|
||||
|
||||
implicit val ec: ExecutionContext = ExecutionContext.global
|
||||
|
||||
// this reads authentication credentials and
|
||||
// connection details from the default data
|
||||
// directory on your platform
|
||||
val client = BitcoindRpcClient.fromDatadir()
|
||||
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
|
||||
|
||||
val balance: Future[Bitcoins] = for {
|
||||
_ <- client.start()
|
||||
@ -98,6 +99,7 @@ import org.bitcoins.rpc.BitcoindWalletException
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.protocol._
|
||||
import org.bitcoins.core.currency._
|
||||
import java.io._
|
||||
|
||||
import scala.concurrent._
|
||||
|
||||
@ -105,7 +107,7 @@ implicit val ec = ExecutionContext.global
|
||||
|
||||
// let's assume you have an already running client,
|
||||
// so there's no need to start this one
|
||||
val cli = BitcoindRpcClient.fromDatadir()
|
||||
val cli = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
|
||||
|
||||
// let's also assume you have a bitcoin address
|
||||
val address: BitcoinAddress = ???
|
||||
|
@ -627,7 +627,8 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||
network = instance.network,
|
||||
uri = new URI("http://localhost:18333"),
|
||||
rpcUri = auth.bitcoindRpcUri,
|
||||
authCredentials = auth.bitcoinAuthOpt.get
|
||||
authCredentials = auth.bitcoinAuthOpt.get,
|
||||
binary = BitcoindRpcTestUtil.newestBitcoindBinary
|
||||
)
|
||||
BitcoindRpcClient.withActorSystem(bitcoindInstance)
|
||||
}
|
||||
|
@ -171,6 +171,8 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
||||
baseBinaryDirectory.resolve("bitcoind")
|
||||
}
|
||||
|
||||
def newestBitcoindBinary: File = getBinary(BitcoindVersion.newest)
|
||||
|
||||
private def getBinary(version: BitcoindVersion): File = version match {
|
||||
// default to newest version
|
||||
case Unknown => getBinary(BitcoindVersion.newest)
|
||||
@ -224,23 +226,16 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
||||
val binary: File = versionOpt match {
|
||||
case Some(version) => getBinary(version)
|
||||
case None =>
|
||||
Try {
|
||||
BitcoindInstance.DEFAULT_BITCOIND_LOCATION
|
||||
}.recoverWith {
|
||||
case _: RuntimeException =>
|
||||
if (Files.exists(
|
||||
BitcoindRpcTestUtil.binaryDirectory
|
||||
)) {
|
||||
Success(getBinary(BitcoindVersion.newest))
|
||||
} else {
|
||||
Failure(new RuntimeException(
|
||||
"Could not locate bitcoind. Make sure it is installed on your PATH, or if working with Bitcoin-S directly, try running 'sbt downloadBitcoind'"))
|
||||
}
|
||||
|
||||
} match {
|
||||
case Failure(exception) => throw exception
|
||||
case Success(value) => value
|
||||
if (Files.exists(
|
||||
BitcoindRpcTestUtil.binaryDirectory
|
||||
)) {
|
||||
newestBitcoindBinary
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Could not locate bitcoind. Make sure it is installed on your PATH, or if working with Bitcoin-S " +
|
||||
"directly, try running 'sbt downloadBitcoind'")
|
||||
}
|
||||
|
||||
}
|
||||
val instance = BitcoindInstance(network = network,
|
||||
uri = uri,
|
||||
@ -708,6 +703,13 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
||||
createNodeTripleInternal(BitcoindVersion.V17, clientAccum)
|
||||
}
|
||||
|
||||
def createNodeTripleV18(
|
||||
clientAccum: RpcClientAccum = Vector.newBuilder
|
||||
)(implicit system: ActorSystem): Future[
|
||||
(BitcoindV18RpcClient, BitcoindV18RpcClient, BitcoindV18RpcClient)] = {
|
||||
createNodeTripleInternal(BitcoindVersion.V18, clientAccum)
|
||||
}
|
||||
|
||||
def createRawCoinbaseTransaction(
|
||||
sender: BitcoindRpcClient,
|
||||
receiver: BitcoindRpcClient,
|
||||
|
Loading…
Reference in New Issue
Block a user