text: // Copyright (c) 2011-2013 The Bitcoin Core developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or https://www.opensource.org/licenses/mit-license.php .
  
  #define BOOST_TEST_MODULE Bitcoin Test Suite
  
  #include "test_bitcoin.h"
  
  #include "crypto/common.h"
  
  #include "key.h"
  #include "main.h"
  #include "random.h"
  #include "chainparamsbase.h"
  #include "txdb.h"
  #include "txmempool.h"
  #include "ui_interface.h"
  #include "rpc/server.h"
  #include "rpc/register.h"
  #include "util.h"
  #ifdef ENABLE_WALLET
  #include "wallet/db.h"
  #include "wallet/wallet.h"
  #endif
  
  #include <boost/filesystem.hpp>
  #include <boost/test/unit_test.hpp>
  #include <boost/thread.hpp>
  
  #include "librustzcash.h"
  
  CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
  CWallet* pwalletMain;
  ZCJoinSplit *pzcashParams;
  
  extern bool fPrintToConsole;
  extern void noui_connect();
  
  JoinSplitTestingSetup::JoinSplitTestingSetup()
  {
      boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
      boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
      pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
  
      boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params";
      boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params";
      boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params";
  
      static_assert(
          sizeof(boost::filesystem::path::value_type) == sizeof(codeunit),
          "librustzcash not configured correctly");
      auto sapling_spend_str = sapling_spend.native();
      auto sapling_output_str = sapling_output.native();
      auto sprout_groth16_str = sprout_groth16.native();
  
      librustzcash_init_zksnark_params(
          reinterpret_cast<const codeunit*>(sapling_spend_str.c_str()),
          sapling_spend_str.length(),
          "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c",
          reinterpret_cast<const codeunit*>(sapling_output_str.c_str()),
          sapling_output_str.length(),
          "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028",
          reinterpret_cast<const codeunit*>(sprout_groth16_str.c_str()),
          sprout_groth16_str.length(),
          "e9b238411bd6c0ec4791e9d04245ec350c9c5744f5610dfcce4365d5ca49dfefd5054e371842b3f88fa1b9d7e8e075249b3ebabd167fa8b0f3161292d36c180a"
      );
  }
  
  JoinSplitTestingSetup::~JoinSplitTestingSetup()
  {
      delete pzcashParams;
  }
  
  BasicTestingSetup::BasicTestingSetup()
  {
      assert(init_and_check_sodium() != -1);
      ECC_Start();
      SetupEnvironment();
      SetupNetworking();
      fPrintToDebugLog = false; // don't want to write to debug.log file
      fCheckBlockIndex = true;
      SelectParams(CBaseChainParams::MAIN);
  }
  BasicTestingSetup::~BasicTestingSetup()
  {
      ECC_Stop();
  }
  
  TestingSetup::TestingSetup()
  {
      const CChainParams& chainparams = Params();
          // Ideally we'd move all the RPC tests to the functional testing framework
          // instead of unit tests, but for now we need these here.
          RegisterAllCoreRPCCommands(tableRPC);
  #ifdef ENABLE_WALLET
          bitdb.MakeMock();
          RegisterWalletRPCCommands(tableRPC);
  #endif
  
          // Save current path, in case a test changes it
          orig_current_path = boost::filesystem::current_path();
  
          ClearDatadirCache();
          pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
          boost::filesystem::create_directories(pathTemp);
          mapArgs["-datadir"] = pathTemp.string();
          pblocktree = new CBlockTreeDB(1 << 20, true);
          pcoinsdbview = new CCoinsViewDB(1 << 23, true);
          pcoinsTip = new CCoinsViewCache(pcoinsdbview);
          InitBlockIndex(chainparams);
  #ifdef ENABLE_WALLET
          bool fFirstRun;
          pwalletMain = new CWallet("wallet.dat");
          pwalletMain->LoadWallet(fFirstRun);
          RegisterValidationInterface(pwalletMain);
  #endif
          nScriptCheckThreads = 3;
          for (int i=0; i < nScriptCheckThreads-1; i++)
              threadGroup.create_thread(&ThreadScriptCheck);
          RegisterNodeSignals(GetNodeSignals());
  }
  
  TestingSetup::~TestingSetup()
  {
          UnregisterNodeSignals(GetNodeSignals());
          threadGroup.interrupt_all();
          threadGroup.join_all();
  #ifdef ENABLE_WALLET
          UnregisterValidationInterface(pwalletMain);
          delete pwalletMain;
          pwalletMain = NULL;
  #endif
          UnloadBlockIndex();
          delete pcoinsTip;
          delete pcoinsdbview;
          delete pblocktree;
  #ifdef ENABLE_WALLET
          bitdb.Flush(true);
          bitdb.Reset();
  #endif
  
          // Restore the previous current path so temporary directory can be deleted
          boost::filesystem::current_path(orig_current_path);
  
          boost::filesystem::remove_all(pathTemp);
  }
  
  
  CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
      return CTxMemPoolEntry(tx, nFee, nTime, dPriority, nHeight,
                             pool ? pool->HasNoInputsOf(tx) : hadNoDependencies,
                             spendsCoinbase, nBranchId);
  }
  
  void Shutdown(void* parg)
  {
    exit(0);
  }
  
  void StartShutdown()
  {
    exit(0);
  }
  
  bool ShutdownRequested()
  {
    return false;
  }
  