<commit_before>package org.bitcoins.testkit.fixtures

import akka.actor.ActorSystem
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
import org.bitcoins.testkit.util.BitcoinSAsyncFixtureTest
import org.scalatest._

import scala.concurrent.{Future, Promise}
import scala.util.{Failure, Success}

object UsesExperimentalBitcoind extends Tag("UsesExperimentalBitcoind")

trait BitcoinSFixture extends BitcoinSAsyncFixtureTest {

  /**
    * Given functions to build and destroy a fixture, returns a OneArgAsyncTest => FutureOutcome
    * (this version gives the destroy function access to the fixture)
    *
    * Example:
    * {{{
    *   makeDependentFixture(createBitcoindChainHandler, destroyBitcoindChainHandler)
    * }}}
    */
  def makeDependentFixture[T](
      build: () => Future[T],
      destroy: T => Future[Any])(test: OneArgAsyncTest): FutureOutcome = {
    val fixtureF = build()

    fixtureF.failed.foreach { err =>
      println(s"Failed to build fixture with err=${err}")
      throw err
    }

    val outcomeF = fixtureF.flatMap { fixture =>
      test(fixture.asInstanceOf[FixtureParam]).toFuture
    }

    outcomeF.failed.foreach(err =>
      println(s"Failed fixture test execution=${err}"))

    val destroyP = Promise[Unit]()
    outcomeF.onComplete { _ =>
      fixtureF.foreach { fixture =>
        destroy(fixture).onComplete {
          case Success(_) => destroyP.success(())
          case Failure(err) =>
            logger.error(s"Failed to destroy fixture with err=${err}")
            destroyP.failure(err)
        }
      }
    }

    val outcomeAfterDestroyF = destroyP.future.flatMap(_ => outcomeF)

    outcomeAfterDestroyF.failed.foreach { err =>
      println(s"err creating and destroying fixture")
      throw err

    }
    new FutureOutcome(outcomeAfterDestroyF)
  }

  /**
    * Given functions to build and destroy a fixture, returns a OneArgAsyncTest => FutureOutcome
    * (this version does not give the destroy function access to the fixture, see makeDependentFixture)
    *
    * Example:
    * {{{
    *   makeFixture(createBlockHeaderDAO, destroyBlockHeaderTable)
    * }}}
    */
  def makeFixture[T](build: () => Future[T], destroy: () => Future[Any])(
      test: OneArgAsyncTest): FutureOutcome = {
    val outcomeF = build().flatMap { fixture =>
      test(fixture.asInstanceOf[FixtureParam]).toFuture
    }

    val destroyP = Promise[Unit]()
    outcomeF.onComplete { _ =>
      destroy().onComplete {
        case Success(_)   => destroyP.success(())
        case Failure(err) => destroyP.failure(err)
      }<commit_msg>Refactor make dependent fixtures to use built in scalatest helper met… (#939)<commit_after>package org.bitcoins.testkit.fixtures

import akka.actor.ActorSystem
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
import org.bitcoins.testkit.util.BitcoinSAsyncFixtureTest
import org.scalatest._

import scala.concurrent.{Future, Promise}
import scala.util.{Failure, Success}

object UsesExperimentalBitcoind extends Tag("UsesExperimentalBitcoind")

trait BitcoinSFixture extends BitcoinSAsyncFixtureTest {

  /**
    * Given functions to build and destroy a fixture, returns a OneArgAsyncTest => FutureOutcome
    * (this version gives the destroy function access to the fixture)
    *
    * Example:
    * {{{
    *   makeDependentFixture(createBitcoindChainHandler, destroyBitcoindChainHandler)
    * }}}
    */
  def makeDependentFixture[T](
      build: () => Future[T],
      destroy: T => Future[Any])(test: OneArgAsyncTest): FutureOutcome = {
    val fixtureF = build()

    fixtureF.failed.foreach { err =>
      println(s"Failed to build fixture with err=${err}")
      throw err
    }

    val outcomeF: Future[Outcome] = fixtureF.flatMap { fixture =>
      test(fixture.asInstanceOf[FixtureParam]).toFuture
    }

    val futOutcome: FutureOutcome = new FutureOutcome(outcomeF)

    val result: FutureOutcome = futOutcome.onOutcomeThen { _ =>
      fixtureF.flatMap(f => destroy(f))
      ()
    }

    result
  }

  /**
    * Given functions to build and destroy a fixture, returns a OneArgAsyncTest => FutureOutcome
    * (this version does not give the destroy function access to the fixture, see makeDependentFixture)
    *
    * Example:
    * {{{
    *   makeFixture(createBlockHeaderDAO, destroyBlockHeaderTable)
    * }}}
    */
  def makeFixture[T](build: () => Future[T], destroy: () => Future[Any])(
      test: OneArgAsyncTest): FutureOutcome = {
    val outcomeF = build().flatMap { fixture =>
      test(fixture.asInstanceOf[FixtureParam]).toFuture
    }

    val destroyP = Promise[Unit]()
    outcomeF.onComplete { _ =>
      destroy().onComplete {
        case Success(_)   => destroyP.success(())
        case Failure(err) => destroyP.failure(err)
      }
{'fraction_non_alphanumeric': 0.10993700467384677, 'fraction_numerical': 0.000609632188579557, 'mean_word_length': 3.4422382671480145, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2145898', 'n_tokens_mistral': 1492, 'n_tokens_neox': 1463, 'n_words': 327}