From 962a1bca0aea4ab37032d1ef13323f85280e62a9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 3 Mar 2015 07:49:12 -0800 Subject: [PATCH] Reinitialize state in between individual unit tests. This changes the TestingSetup fixture to be per-unit-test rather than global. Most tests don't need it, so it's only invoked in a few. --- src/Makefile.test.include | 1 + src/main.cpp | 23 +- src/test/Checkpoints_tests.cpp | 3 +- src/test/DoS_tests.cpp | 4 +- src/test/accounting_tests.cpp | 4 +- src/test/alert_tests.cpp | 4 +- src/test/benchmark_zerocoin.cpp | 4 +- src/test/budget_tests.cpp | 3 +- src/test/key_tests.cpp | 3 +- src/test/libzerocoin_tests.cpp | 681 +++++++++++---------- src/test/main_tests.cpp | 3 +- src/test/miner_tests.cpp | 4 +- src/test/multisig_tests.cpp | 3 +- src/test/rpc_tests.cpp | 4 +- src/test/rpc_wallet_tests.cpp | 4 +- src/test/sanity_tests.cpp | 3 +- src/test/script_P2SH_tests.cpp | 4 +- src/test/script_tests.cpp | 5 +- src/test/sighash_tests.cpp | 3 +- src/test/sigopcount_tests.cpp | 3 +- src/test/test_pivx.cpp | 31 +- src/test/test_pivx.h | 19 + src/test/transaction_tests.cpp | 3 +- src/test/tutorial_zerocoin.cpp | 11 +- src/test/zerocoin_implementation_tests.cpp | 3 +- src/util.h | 3 +- src/wallet/db.cpp | 83 +-- src/wallet/db.h | 6 +- src/wallet/test/wallet_tests.cpp | 3 +- src/wallet/walletdb.cpp | 16 +- 30 files changed, 511 insertions(+), 433 deletions(-) create mode 100644 src/test/test_pivx.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index b240903e932a1..6d2eca216117e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -23,6 +23,7 @@ RAW_TEST_FILES = test/data/alertTests.raw GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ + test/test_pivx.h \ test/test_pivx.cpp # test_pivx binary # BITCOIN_TESTS =\ diff --git a/src/main.cpp b/src/main.cpp index 4fd9ac8c236e7..553d2744d9d33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5294,10 +5294,31 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth void UnloadBlockIndex() { - mapBlockIndex.clear(); + LOCK(cs_main); setBlockIndexCandidates.clear(); chainActive.SetTip(NULL); pindexBestInvalid = NULL; + pindexBestHeader = NULL; + mempool.clear(); + mapOrphanTransactions.clear(); + mapOrphanTransactionsByPrev.clear(); + nSyncStarted = 0; + mapBlocksUnlinked.clear(); + vinfoBlockFile.clear(); + nLastBlockFile = 0; + nBlockSequenceId = 1; + mapBlockSource.clear(); + mapBlocksInFlight.clear(); + nQueuedValidatedHeaders = 0; + nPreferredDownload = 0; + setDirtyBlockIndex.clear(); + setDirtyFileInfo.clear(); + mapNodeState.clear(); + + for (BlockMap::value_type& entry : mapBlockIndex) { + delete entry.second; + } + mapBlockIndex.clear(); } bool LoadBlockIndex(string& strError) diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index 3ded248b17e4a..0788966999aca 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -10,12 +10,13 @@ #include "checkpoints.h" #include "uint256.h" +#include "test_pivx.h" #include using namespace std; -BOOST_AUTO_TEST_SUITE(Checkpoints_tests) +BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, TestingSetup) BOOST_AUTO_TEST_CASE(sanity) { diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 780b214400918..29d5efd97b223 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -16,6 +16,8 @@ #include "serialize.h" #include "util.h" +#include "test/test_pivx.h" + #include #include // for 'map_list_of()' @@ -40,7 +42,7 @@ CService ip(uint32_t i) return CService(CNetAddr(s), Params().GetDefaultPort()); } -BOOST_AUTO_TEST_SUITE(DoS_tests) +BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 3f5d4bcab5d63..a2c955ccd2ea8 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -6,13 +6,15 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" +#include "test/test_pivx.h" + #include #include extern CWallet* pwalletMain; -BOOST_AUTO_TEST_SUITE(accounting_tests) +BOOST_FIXTURE_TEST_SUITE(accounting_tests, TestingSetup) static void GetResults(CWalletDB& walletdb, std::map& results) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 406b569e223df..c7dd4d3594e30 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -15,6 +15,8 @@ #include "util.h" #include "utilstrencodings.h" +#include "test/test_bitcoin.h" + #include #include @@ -77,7 +79,7 @@ } #endif -struct ReadAlerts +struct ReadAlerts : public TestingSetup { ReadAlerts() { diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp index c3aee3e0786ee..785fcc80ec796 100644 --- a/src/test/benchmark_zerocoin.cpp +++ b/src/test/benchmark_zerocoin.cpp @@ -25,6 +25,7 @@ #include "libzerocoin/Coin.h" #include "libzerocoin/CoinSpend.h" #include "libzerocoin/Accumulator.h" +#include "test_pivx.h" using namespace std; using namespace libzerocoin; @@ -402,7 +403,8 @@ Testb_RunAllTests() cout << ggSuccessfulTests << " out of " << ggNumTests << " tests passed." << endl << endl; delete gg_Params; } -BOOST_AUTO_TEST_SUITE(benchmark_zerocoin) + +BOOST_FIXTURE_TEST_SUITE(benchmark_zerocoin, TestingSetup) BOOST_AUTO_TEST_CASE(benchmark_test) { diff --git a/src/test/budget_tests.cpp b/src/test/budget_tests.cpp index 204a3ff3e5b65..abb4c6723d28f 100644 --- a/src/test/budget_tests.cpp +++ b/src/test/budget_tests.cpp @@ -5,10 +5,11 @@ #include "masternode-budget.h" #include "tinyformat.h" #include "utilmoneystr.h" +#include "test_pivx.h" #include -BOOST_AUTO_TEST_SUITE(budget_tests) +BOOST_FIXTURE_TEST_SUITE(budget_tests, TestingSetup) void CheckBudgetValue(int nHeight, std::string strNetwork, CAmount nExpectedValue) { diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 3ae28e17c43df..1a7a5a6fa29e1 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -10,6 +10,7 @@ #include "uint256.h" #include "util.h" #include "utilstrencodings.h" +#include "test_pivx.h" #include #include @@ -59,7 +60,7 @@ void dumpKeyInfo(uint256 privkey) #endif -BOOST_AUTO_TEST_SUITE(key_tests) +BOOST_FIXTURE_TEST_SUITE(key_tests, TestingSetup) BOOST_AUTO_TEST_CASE(key_test1) { diff --git a/src/test/libzerocoin_tests.cpp b/src/test/libzerocoin_tests.cpp index 77bde281209b3..fb1fb547b9dc5 100644 --- a/src/test/libzerocoin_tests.cpp +++ b/src/test/libzerocoin_tests.cpp @@ -24,6 +24,7 @@ #include "libzerocoin/Coin.h" #include "libzerocoin/CoinSpend.h" #include "libzerocoin/Accumulator.h" +#include "test_pivx.h" using namespace std; using namespace libzerocoin; @@ -33,16 +34,16 @@ using namespace libzerocoin; #define COLOR_STR_RED "\033[31m" #define TESTS_COINS_TO_ACCUMULATE 10 -#define NON_PRIME_TESTS 100 +#define NON_PRIME_TESTS 100 // Global test counters uint32_t gNumTests = 0; uint32_t gSuccessfulTests = 0; // Proof size -uint32_t gProofSize = 0; -uint32_t gCoinSize = 0; -uint32_t gSerialNumberSize = 0; +uint32_t gProofSize = 0; +uint32_t gCoinSize = 0; +uint32_t gSerialNumberSize = 0; // Global coin array PrivateCoin *gCoins[TESTS_COINS_TO_ACCUMULATE]; @@ -57,42 +58,42 @@ ZerocoinParams *g_Params; void LogTestResult(string testName, bool (*testPtr)()) { - string colorGreen(COLOR_STR_GREEN); - string colorNormal(COLOR_STR_NORMAL); - string colorRed(COLOR_STR_RED); + string colorGreen(COLOR_STR_GREEN); + string colorNormal(COLOR_STR_NORMAL); + string colorRed(COLOR_STR_RED); - cout << "Testing if " << testName << "..." << endl; + cout << "Testing if " << testName << "..." << endl; - bool testResult = testPtr(); + bool testResult = testPtr(); - if (testResult == true) { - cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; - gSuccessfulTests++; - } else { - cout << colorRed << "\t[FAIL]" << colorNormal << endl; - } + if (testResult == true) { + cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; + gSuccessfulTests++; + } else { + cout << colorRed << "\t[FAIL]" << colorNormal << endl; + } - gNumTests++; + gNumTests++; } CBigNum GetTestModulus() { - static CBigNum testModulus(0); + static CBigNum testModulus(0); - // TODO: should use a hard-coded RSA modulus for testing - if (!testModulus) { - CBigNum p, q; + // TODO: should use a hard-coded RSA modulus for testing + if (!testModulus) { + CBigNum p, q; - // Note: we are NOT using safe primes for testing because - // they take too long to generate. Don't do this in real - // usage. See the paramgen utility for better code. - p = CBigNum::generatePrime(1024, false); - q = CBigNum::generatePrime(1024, false); - testModulus = p * q; - } + // Note: we are NOT using safe primes for testing because + // they take too long to generate. Don't do this in real + // usage. See the paramgen utility for better code. + p = CBigNum::generatePrime(1024, false); + q = CBigNum::generatePrime(1024, false); + testModulus = p * q; + } - return testModulus; + return testModulus; } ////////// @@ -102,393 +103,393 @@ GetTestModulus() bool Test_GenRSAModulus() { - CBigNum result = GetTestModulus(); - - if (!result) { - return false; - } - else { - return true; - } + CBigNum result = GetTestModulus(); + + if (!result) { + return false; + } + else { + return true; + } } bool Test_CalcParamSizes() { - bool result = true; + bool result = true; #if 0 - uint32_t pLen, qLen; - - try { - calculateGroupParamLengths(4000, 80, &pLen, &qLen); - if (pLen < 1024 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 96, &pLen, &qLen); - if (pLen < 2048 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 112, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 120, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 128, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - } catch (exception &e) { - result = false; - } + uint32_t pLen, qLen; + + try { + calculateGroupParamLengths(4000, 80, &pLen, &qLen); + if (pLen < 1024 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 96, &pLen, &qLen); + if (pLen < 2048 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 112, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 120, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 128, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + } catch (exception &e) { + result = false; + } #endif - return result; + return result; } bool Test_GenerateGroupParams() { - uint32_t pLen = 1024, qLen = 256, count; - IntegerGroupParams group; + uint32_t pLen = 1024, qLen = 256, count; + IntegerGroupParams group; - for (count = 0; count < 1; count++) { + for (count = 0; count < 1; count++) { - try { - group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (std::runtime_error e) { - cout << "Caught exception " << e.what() << endl; - return false; - } + try { + group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (std::runtime_error e) { + cout << "Caught exception " << e.what() << endl; + return false; + } - // Now perform some simple tests on the resulting parameters - if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { - return false; - } + // Now perform some simple tests on the resulting parameters + if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { + return false; + } - CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); - //cout << "g^q mod p = " << c << endl; - if (!(c.isOne())) return false; + CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); + //cout << "g^q mod p = " << c << endl; + if (!(c.isOne())) return false; - // Try at multiple parameter sizes - pLen = pLen * 1.5; - qLen = qLen * 1.5; - } + // Try at multiple parameter sizes + pLen = pLen * 1.5; + qLen = qLen * 1.5; + } - return true; + return true; } bool Test_ParamGen() { - bool result = true; + bool result = true; - try { - // Instantiating testParams runs the parameter generation code - ZerocoinParams testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - } catch (runtime_error e) { - cout << e.what() << endl; - result = false; - } + try { + // Instantiating testParams runs the parameter generation code + ZerocoinParams testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); + } catch (runtime_error e) { + cout << e.what() << endl; + result = false; + } - return result; + return result; } bool Test_Accumulator() { - // This test assumes a list of coins were generated during - // the Test_MintCoin() test. - if (gCoins[0] == NULL) { - return false; - } - try { - // Accumulate the coin list from first to last into one accumulator + // This test assumes a list of coins were generated during + // the Test_MintCoin() test. + if (gCoins[0] == NULL) { + return false; + } + try { + // Accumulate the coin list from first to last into one accumulator Accumulator accOne(&g_Params->accumulatorParams, CoinDenomination::ZQ_ONE); Accumulator accTwo(&g_Params->accumulatorParams,CoinDenomination::ZQ_ONE); Accumulator accThree(&g_Params->accumulatorParams,CoinDenomination::ZQ_ONE); Accumulator accFour(&g_Params->accumulatorParams,CoinDenomination::ZQ_ONE); - AccumulatorWitness wThree(g_Params, accThree, gCoins[0]->getPublicCoin()); - - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - accOne += gCoins[i]->getPublicCoin(); - accTwo += gCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); - accThree += gCoins[i]->getPublicCoin(); - wThree += gCoins[i]->getPublicCoin(); - if(i != 0) { - accFour += gCoins[i]->getPublicCoin(); - } - } - - // Compare the accumulated results - if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { - cout << "Accumulators don't match" << endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - cout << "Witness math not working," << endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { - cout << "Witness not valid" << endl; - return false; - } - - // Serialization test: see if we can serialize the accumulator - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << accOne; - - // Deserialize it into a new object - Accumulator newAcc(g_Params, ss); - - // Compare the results - if (accOne.getValue() != newAcc.getValue()) { - return false; - } - - } catch (runtime_error e) { - return false; - } - - return true; + AccumulatorWitness wThree(g_Params, accThree, gCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + accOne += gCoins[i]->getPublicCoin(); + accTwo += gCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); + accThree += gCoins[i]->getPublicCoin(); + wThree += gCoins[i]->getPublicCoin(); + if(i != 0) { + accFour += gCoins[i]->getPublicCoin(); + } + } + + // Compare the accumulated results + if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { + cout << "Accumulators don't match" << endl; + return false; + } + + if(accFour.getValue() != wThree.getValue()) { + cout << "Witness math not working," << endl; + return false; + } + + // Verify that the witness is correct + if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { + cout << "Witness not valid" << endl; + return false; + } + + // Serialization test: see if we can serialize the accumulator + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << accOne; + + // Deserialize it into a new object + Accumulator newAcc(g_Params, ss); + + // Compare the results + if (accOne.getValue() != newAcc.getValue()) { + return false; + } + + } catch (runtime_error e) { + return false; + } + + return true; } bool Test_EqualityPoK() { - // Run this test 10 times - for (uint32_t i = 0; i < 10; i++) { - try { - // Generate a random integer "val" - CBigNum val = CBigNum::randBignum(g_Params->coinCommitmentGroup.groupOrder); - - // Manufacture two commitments to "val", both - // under different sets of parameters - Commitment one(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, val); - - Commitment two(&g_Params->serialNumberSoKCommitmentGroup, val); - - // Now generate a proof of knowledge that "one" and "two" are - // both commitments to the same value - CommitmentProofOfKnowledge pok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - one, two); - - // Serialize the proof into a stream - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pok; - - // Deserialize back into a PoK object - CommitmentProofOfKnowledge newPok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - ss); - - if (newPok.Verify(one.getCommitmentValue(), two.getCommitmentValue()) != true) { - return false; - } - - // Just for fun, deserialize the proof a second time - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << pok; - - // This time tamper with it, then deserialize it back into a PoK - ss2[15] = 0; - CommitmentProofOfKnowledge newPok2(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - ss2); - - // If the tampered proof verifies, that's a failure! - if (newPok2.Verify(one.getCommitmentValue(), two.getCommitmentValue()) == true) { - return false; - } - - } catch (runtime_error &e) { - return false; - } - } - - return true; + // Run this test 10 times + for (uint32_t i = 0; i < 10; i++) { + try { + // Generate a random integer "val" + CBigNum val = CBigNum::randBignum(g_Params->coinCommitmentGroup.groupOrder); + + // Manufacture two commitments to "val", both + // under different sets of parameters + Commitment one(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, val); + + Commitment two(&g_Params->serialNumberSoKCommitmentGroup, val); + + // Now generate a proof of knowledge that "one" and "two" are + // both commitments to the same value + CommitmentProofOfKnowledge pok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + one, two); + + // Serialize the proof into a stream + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pok; + + // Deserialize back into a PoK object + CommitmentProofOfKnowledge newPok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss); + + if (newPok.Verify(one.getCommitmentValue(), two.getCommitmentValue()) != true) { + return false; + } + + // Just for fun, deserialize the proof a second time + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << pok; + + // This time tamper with it, then deserialize it back into a PoK + ss2[15] = 0; + CommitmentProofOfKnowledge newPok2(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss2); + + // If the tampered proof verifies, that's a failure! + if (newPok2.Verify(one.getCommitmentValue(), two.getCommitmentValue()) == true) { + return false; + } + + } catch (runtime_error &e) { + return false; + } + } + + return true; } bool Test_MintCoin() { - gCoinSize = 0; + gCoinSize = 0; - try { - // Generate a list of coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + try { + // Generate a list of coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { gCoins[i] = new PrivateCoin(g_Params,libzerocoin::CoinDenomination::ZQ_ONE); - PublicCoin pc = gCoins[i]->getPublicCoin(); - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pc; - gCoinSize += ss.size(); - } + PublicCoin pc = gCoins[i]->getPublicCoin(); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pc; + gCoinSize += ss.size(); + } - gCoinSize /= TESTS_COINS_TO_ACCUMULATE; + gCoinSize /= TESTS_COINS_TO_ACCUMULATE; - } catch (exception &e) { - return false; - } + } catch (exception &e) { + return false; + } - return true; + return true; } bool Test_InvalidCoin() { - CBigNum coinValue; - - try { - // Pick a random non-prime CBigNum - for (uint32_t i = 0; i < NON_PRIME_TESTS; i++) { - coinValue = CBigNum::randBignum(g_Params->coinCommitmentGroup.modulus); - coinValue = coinValue * 2; - if (!coinValue.isPrime()) break; - } - - PublicCoin pubCoin(g_Params); - if (pubCoin.validate()) { - // A blank coin should not be valid! - return false; - } - - PublicCoin pubCoin2(g_Params, coinValue, ZQ_ONE); - if (pubCoin2.validate()) { - // A non-prime coin should not be valid! - return false; - } - - PublicCoin pubCoin3 = pubCoin2; - if (pubCoin2.validate()) { - // A copy of a non-prime coin should not be valid! - return false; - } - - // Serialize and deserialize the coin - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pubCoin; - PublicCoin pubCoin4(g_Params, ss); - if (pubCoin4.validate()) { - // A deserialized copy of a non-prime coin should not be valid! - return false; - } - - } catch (runtime_error &e) { - cout << "Caught exception: " << e.what() << endl; - return false; - } - - return true; + CBigNum coinValue; + + try { + // Pick a random non-prime CBigNum + for (uint32_t i = 0; i < NON_PRIME_TESTS; i++) { + coinValue = CBigNum::randBignum(g_Params->coinCommitmentGroup.modulus); + coinValue = coinValue * 2; + if (!coinValue.isPrime()) break; + } + + PublicCoin pubCoin(g_Params); + if (pubCoin.validate()) { + // A blank coin should not be valid! + return false; + } + + PublicCoin pubCoin2(g_Params, coinValue, ZQ_ONE); + if (pubCoin2.validate()) { + // A non-prime coin should not be valid! + return false; + } + + PublicCoin pubCoin3 = pubCoin2; + if (pubCoin2.validate()) { + // A copy of a non-prime coin should not be valid! + return false; + } + + // Serialize and deserialize the coin + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pubCoin; + PublicCoin pubCoin4(g_Params, ss); + if (pubCoin4.validate()) { + // A deserialized copy of a non-prime coin should not be valid! + return false; + } + + } catch (runtime_error &e) { + cout << "Caught exception: " << e.what() << endl; + return false; + } + + return true; } bool Test_MintAndSpend() { - try { - // This test assumes a list of coins were generated in Test_MintCoin() - if (gCoins[0] == NULL) - { - // No coins: mint some. - Test_MintCoin(); - if (gCoins[0] == NULL) { - return false; - } - } - - // Accumulate the list of generated coins into a fresh accumulator. - // The first one gets marked as accumulated for a witness, the - // others just get accumulated normally. + try { + // This test assumes a list of coins were generated in Test_MintCoin() + if (gCoins[0] == NULL) + { + // No coins: mint some. + Test_MintCoin(); + if (gCoins[0] == NULL) { + return false; + } + } + + // Accumulate the list of generated coins into a fresh accumulator. + // The first one gets marked as accumulated for a witness, the + // others just get accumulated normally. Accumulator acc(&g_Params->accumulatorParams,CoinDenomination::ZQ_ONE); - AccumulatorWitness wAcc(g_Params, acc, gCoins[0]->getPublicCoin()); + AccumulatorWitness wAcc(g_Params, acc, gCoins[0]->getPublicCoin()); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - acc += gCoins[i]->getPublicCoin(); - wAcc +=gCoins[i]->getPublicCoin(); - } + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + acc += gCoins[i]->getPublicCoin(); + wAcc +=gCoins[i]->getPublicCoin(); + } - // Now spend the coin - //SpendMetaData m(1,1); - CDataStream cc(SER_NETWORK, PROTOCOL_VERSION); - cc << *gCoins[0]; - PrivateCoin myCoin(g_Params,cc); + // Now spend the coin + //SpendMetaData m(1,1); + CDataStream cc(SER_NETWORK, PROTOCOL_VERSION); + cc << *gCoins[0]; + PrivateCoin myCoin(g_Params,cc); - CoinSpend spend(g_Params, g_Params, myCoin, acc, 0, wAcc, 0, SpendType::SPEND); + CoinSpend spend(g_Params, g_Params, myCoin, acc, 0, wAcc, 0, SpendType::SPEND); spend.Verify(acc); - // Serialize the proof and deserialize into newSpend - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << spend; - gProofSize = ss.size(); - CoinSpend newSpend(g_Params, g_Params, ss); - - // See if we can verify the deserialized proof (return our result) - bool ret = newSpend.Verify(acc); - - // Extract the serial number - CBigNum serialNumber = newSpend.getCoinSerialNumber(); - gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); - - return ret; - } catch (runtime_error &e) { - cout << e.what() << endl; - return false; - } - - return false; + // Serialize the proof and deserialize into newSpend + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << spend; + gProofSize = ss.size(); + CoinSpend newSpend(g_Params, g_Params, ss); + + // See if we can verify the deserialized proof (return our result) + bool ret = newSpend.Verify(acc); + + // Extract the serial number + CBigNum serialNumber = newSpend.getCoinSerialNumber(); + gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); + + return ret; + } catch (runtime_error &e) { + cout << e.what() << endl; + return false; + } + + return false; } void Test_RunAllTests() { - // Make a new set of parameters from a random RSA modulus - g_Params = new ZerocoinParams(GetTestModulus()); - - gNumTests = gSuccessfulTests = gProofSize = 0; - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - gCoins[i] = NULL; - } - - // Run through all of the Zerocoin tests - LogTestResult("an RSA modulus can be generated", Test_GenRSAModulus); - LogTestResult("parameter sizes are correct", Test_CalcParamSizes); - LogTestResult("group/field parameters can be generated", Test_GenerateGroupParams); - LogTestResult("parameter generation is correct", Test_ParamGen); - LogTestResult("coins can be minted", Test_MintCoin); - LogTestResult("invalid coins will be rejected", Test_InvalidCoin); - LogTestResult("the accumulator works", Test_Accumulator); - LogTestResult("the commitment equality PoK works", Test_EqualityPoK); - LogTestResult("a minted coin can be spent", Test_MintAndSpend); - - cout << endl << "Average coin size is " << gCoinSize << " bytes." << endl; - cout << "Serial number size is " << gSerialNumberSize << " bytes." << endl; - cout << "Spend proof size is " << gProofSize << " bytes." << endl; - - // Summarize test results - if (gSuccessfulTests < gNumTests) { - cout << endl << "ERROR: SOME TESTS FAILED" << endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete gCoins[i]; - } - - cout << endl << gSuccessfulTests << " out of " << gNumTests << " tests passed." << endl << endl; - delete g_Params; + // Make a new set of parameters from a random RSA modulus + g_Params = new ZerocoinParams(GetTestModulus()); + + gNumTests = gSuccessfulTests = gProofSize = 0; + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + gCoins[i] = NULL; + } + + // Run through all of the Zerocoin tests + LogTestResult("an RSA modulus can be generated", Test_GenRSAModulus); + LogTestResult("parameter sizes are correct", Test_CalcParamSizes); + LogTestResult("group/field parameters can be generated", Test_GenerateGroupParams); + LogTestResult("parameter generation is correct", Test_ParamGen); + LogTestResult("coins can be minted", Test_MintCoin); + LogTestResult("invalid coins will be rejected", Test_InvalidCoin); + LogTestResult("the accumulator works", Test_Accumulator); + LogTestResult("the commitment equality PoK works", Test_EqualityPoK); + LogTestResult("a minted coin can be spent", Test_MintAndSpend); + + cout << endl << "Average coin size is " << gCoinSize << " bytes." << endl; + cout << "Serial number size is " << gSerialNumberSize << " bytes." << endl; + cout << "Spend proof size is " << gProofSize << " bytes." << endl; + + // Summarize test results + if (gSuccessfulTests < gNumTests) { + cout << endl << "ERROR: SOME TESTS FAILED" << endl; + } + + // Clear any generated coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + delete gCoins[i]; + } + + cout << endl << gSuccessfulTests << " out of " << gNumTests << " tests passed." << endl << endl; + delete g_Params; } -BOOST_AUTO_TEST_SUITE(libzerocoin) +BOOST_FIXTURE_TEST_SUITE(libzerocoin, TestingSetup) BOOST_AUTO_TEST_CASE(libzerocoin_tests) { - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " test utility." << endl << endl; - - Test_RunAllTests(); + cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " test utility." << endl << endl; + + Test_RunAllTests(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index dcc7ff64f000f..14eed14bb8f52 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -6,10 +6,11 @@ #include "primitives/transaction.h" #include "main.h" +#include "test_pivx.h" #include -BOOST_AUTO_TEST_SUITE(main_tests) +BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) CAmount nMoneySupplyPoWEnd = 43199500 * COIN; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 47980eb6c1633..2a6af712feec3 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -10,9 +10,11 @@ #include "uint256.h" #include "util.h" +#include "test/test_bitcoin.h" + #include -BOOST_AUTO_TEST_SUITE(miner_tests) +BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) static struct { diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index a1e8c3030c409..19c1919237c03 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -10,6 +10,7 @@ #include "script/interpreter.h" #include "script/sign.h" #include "uint256.h" +#include "test_pivx.h" #ifdef ENABLE_WALLET #include "wallet/wallet_ismine.h" @@ -23,7 +24,7 @@ using namespace boost::assign; typedef vector valtype; -BOOST_AUTO_TEST_SUITE(multisig_tests) +BOOST_FIXTURE_TEST_SUITE(multisig_tests, TestingSetup) CScript sign_multisig(CScript scriptPubKey, vector keys, CTransaction transaction, int whichIn) diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index af14d8ca3cffa..989c5d2f9946e 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -10,6 +10,8 @@ #include "netbase.h" #include "util.h" +#include "test/test_pivx.h" + #include #include @@ -48,7 +50,7 @@ UniValue CallRPC(string args) } -BOOST_AUTO_TEST_SUITE(rpc_tests) +BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_rawparams) { diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 935c7cedbfb0e..e4df6750e55b5 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -9,6 +9,8 @@ #include "base58.h" #include "wallet/wallet.h" +#include "test/test_pivx.h" + #include #include @@ -21,7 +23,7 @@ extern UniValue CallRPC(string args); extern CWallet* pwalletMain; -BOOST_AUTO_TEST_SUITE(rpc_wallet_tests) +BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_addmultisig) { diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 464a8fbb8cfb7..b0d156788bafc 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -4,9 +4,10 @@ #include "compat/sanity.h" #include "key.h" +#include "test_pivx.h" #include -BOOST_AUTO_TEST_SUITE(sanity_tests) +BOOST_FIXTURE_TEST_SUITE(sanity_tests, TestingSetup) BOOST_AUTO_TEST_CASE(basic_sanity) { diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 369093a12b46d..15cd22fda8699 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -8,6 +8,7 @@ #include "script/script.h" #include "script/script_error.h" #include "script/sign.h" +#include "test_pivx.h" #ifdef ENABLE_WALLET #include "wallet/wallet_ismine.h" @@ -46,8 +47,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err); } - -BOOST_AUTO_TEST_SUITE(script_P2SH_tests) +BOOST_FIXTURE_TEST_SUITE(script_P2SH_tests, TestingSetup) BOOST_AUTO_TEST_CASE(sign) { diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index cd9ecb03a979d..2e6095397163d 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -14,6 +14,7 @@ #include "script/script_error.h" #include "script/sign.h" #include "util.h" +#include "test_pivx.h" #if defined(HAVE_CONSENSUS_LIB) #include "script/bitcoinconsensus.h" @@ -58,7 +59,7 @@ read_json(const std::string& jsondata) return v.get_array(); } -BOOST_AUTO_TEST_SUITE(script_tests) +BOOST_FIXTURE_TEST_SUITE(script_tests, TestingSetup) CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) { @@ -826,7 +827,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); -} +} BOOST_AUTO_TEST_CASE(script_combineSigs) { diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 767eaa16c056d..1e4a11f4953a0 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,6 +11,7 @@ #include "script/interpreter.h" #include "util.h" #include "version.h" +#include "test_pivx.h" #include @@ -113,7 +114,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { } } -BOOST_AUTO_TEST_SUITE(sighash_tests) +BOOST_FIXTURE_TEST_SUITE(sighash_tests, TestingSetup) BOOST_AUTO_TEST_CASE(sighash_test) { diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 7abe820ad6745..b5bc53b6416e7 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -8,6 +8,7 @@ #include "script/script.h" #include "script/standard.h" #include "uint256.h" +#include "test_pivx.h" #include @@ -23,7 +24,7 @@ Serialize(const CScript& s) return sSerialized; } -BOOST_AUTO_TEST_SUITE(sigopcount_tests) +BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, TestingSetup) BOOST_AUTO_TEST_CASE(GetSigOpCount) { diff --git a/src/test/test_pivx.cpp b/src/test/test_pivx.cpp index 364119cfbf970..270eb56f442e6 100644 --- a/src/test/test_pivx.cpp +++ b/src/test/test_pivx.cpp @@ -5,6 +5,8 @@ #define BOOST_TEST_MODULE Pivx Test Suite +#include "test_pivx.h" + #include "main.h" #include "random.h" #include "txdb.h" @@ -15,9 +17,7 @@ #include "wallet/wallet.h" #endif -#include #include -#include CClientUIInterface uiInterface; CWallet* pwalletMain; @@ -25,13 +25,8 @@ CWallet* pwalletMain; extern bool fPrintToConsole; extern void noui_connect(); -struct TestingSetup { - CCoinsViewDB *pcoinsdbview; - boost::filesystem::path pathTemp; - boost::thread_group threadGroup; - ECCVerifyHandle globalVerifyHandle; - - TestingSetup() { +TestingSetup::TestingSetup() +{ ECC_Start(); SetupEnvironment(); fPrintToDebugLog = false; // don't want to write to debug.log file @@ -41,6 +36,7 @@ struct TestingSetup { #ifdef ENABLE_WALLET bitdb.MakeMock(); #endif + ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_pivx_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); boost::filesystem::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); @@ -58,28 +54,29 @@ struct TestingSetup { for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); RegisterNodeSignals(GetNodeSignals()); - } - ~TestingSetup() - { +} + +TestingSetup::~TestingSetup() +{ + UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); - UnregisterNodeSignals(GetNodeSignals()); #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 boost::filesystem::remove_all(pathTemp); ECC_Stop(); - } -}; - -BOOST_GLOBAL_FIXTURE(TestingSetup); +} void Shutdown(void* parg) { diff --git a/src/test/test_pivx.h b/src/test/test_pivx.h new file mode 100644 index 0000000000000..815f9a7747b46 --- /dev/null +++ b/src/test/test_pivx.h @@ -0,0 +1,19 @@ +#ifndef PIVX_TEST_TEST_PIVX_H +#define PIVX_TEST_TEST_PIVX_H + +#include "txdb.h" + +#include +#include + +struct TestingSetup { + CCoinsViewDB *pcoinsdbview; + boost::filesystem::path pathTemp; + boost::thread_group threadGroup; + ECCVerifyHandle globalVerifyHandle; + + TestingSetup(); + ~TestingSetup(); +}; + +#endif diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 7706c1ffc1182..c2e611b7ce3c2 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -13,6 +13,7 @@ #include "script/script.h" #include "script/script_error.h" #include "core_io.h" +#include "test_pivx.h" #include #include @@ -79,7 +80,7 @@ string FormatScriptFlags(unsigned int flags) return ret.substr(0, ret.size() - 1); } -BOOST_AUTO_TEST_SUITE(transaction_tests) +BOOST_FIXTURE_TEST_SUITE(transaction_tests, TestingSetup) BOOST_AUTO_TEST_CASE(tx_valid) { diff --git a/src/test/tutorial_zerocoin.cpp b/src/test/tutorial_zerocoin.cpp index 5e86340ffbbd9..3433d6cc5ff9c 100644 --- a/src/test/tutorial_zerocoin.cpp +++ b/src/test/tutorial_zerocoin.cpp @@ -24,6 +24,7 @@ #include "libzerocoin/Coin.h" #include "libzerocoin/CoinSpend.h" #include "libzerocoin/Accumulator.h" +#include "test_pivx.h" using namespace std; @@ -128,7 +129,7 @@ ZerocoinTutorial() // accepted as a valid transaction in the block chain. cout << "Error: coin is not valid!"; } - + cout << "Deserialized and verified the coin." << endl; /********************************************************************/ @@ -217,11 +218,11 @@ ZerocoinTutorial() cout << "ERROR: Our new CoinSpend transaction did not verify!" << endl; return false; } - + // Serialize the CoinSpend object into a buffer. CDataStream serializedCoinSpend(SER_NETWORK, PROTOCOL_VERSION); serializedCoinSpend << spend; - + cout << "Successfully generated a coin spend transaction." << endl; /********************************************************************/ @@ -241,7 +242,7 @@ ZerocoinTutorial() // Create a new metadata object to contain the hash of the received // ZEROCOIN_SPEND transaction. If we were a real client we'd actually // compute the hash of the received transaction here. - + // If we were a real client we would now re-compute the Accumulator // from the information given in the ZEROCOIN_SPEND transaction. // For our purposes we'll just use the one we calculated above. @@ -273,7 +274,7 @@ ZerocoinTutorial() return false; } -BOOST_AUTO_TEST_SUITE(tutorial_libzerocoin) +BOOST_FIXTURE_TEST_SUITE(tutorial_libzerocoin, TestingSetup) BOOST_AUTO_TEST_CASE(tutorial_libzerocoin_tests) { cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " tutorial." << endl << endl; diff --git a/src/test/zerocoin_implementation_tests.cpp b/src/test/zerocoin_implementation_tests.cpp index 82091d386aca1..e7541f4212bf6 100644 --- a/src/test/zerocoin_implementation_tests.cpp +++ b/src/test/zerocoin_implementation_tests.cpp @@ -17,12 +17,13 @@ #include "wallet/wallet.h" #include "zpiv/zpivwallet.h" #include "zpivchain.h" +#include "test_pivx.h" using namespace libzerocoin; extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); -BOOST_AUTO_TEST_SUITE(zerocoin_implementation_tests) +BOOST_FIXTURE_TEST_SUITE(zerocoin_implementation_tests, TestingSetup) BOOST_AUTO_TEST_CASE(zcparams_test) { diff --git a/src/util.h b/src/util.h index 2d369395d249c..3b54286b3baf2 100644 --- a/src/util.h +++ b/src/util.h @@ -119,7 +119,8 @@ void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool TryCreateDirectory(const boost::filesystem::path& p); boost::filesystem::path GetDefaultDataDir(); -const boost::filesystem::path& GetDataDir(bool fNetSpecific = true); +const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +void ClearDatadirCache(); boost::filesystem::path GetConfigFile(); boost::filesystem::path GetMasternodeConfigFile(); #ifndef WIN32 diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 21fbf924ad291..418aa0e7e618c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -40,22 +40,31 @@ void CDBEnv::EnvShutdown() return; fDbEnvInit = false; - int ret = dbenv.close(0); + int ret = dbenv->close(0); if (ret != 0) LogPrintf("CDBEnv::EnvShutdown : Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); if (!fMockDb) DbEnv(0).remove(strPath.c_str(), 0); } -CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS) +void CDBEnv::Reset() { + delete dbenv; + dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS); fDbEnvInit = false; fMockDb = false; } +CDBEnv::CDBEnv() : dbenv(NULL) +{ + Reset(); +} + CDBEnv::~CDBEnv() { EnvShutdown(); + delete dbenv; + dbenv = NULL; } void CDBEnv::Close() @@ -80,17 +89,17 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) if (GetBoolArg("-privdb", true)) nEnvFlags |= DB_PRIVATE; - dbenv.set_lg_dir(pathLogDir.string().c_str()); - dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet - dbenv.set_lg_bsize(0x10000); - dbenv.set_lg_max(1048576); - dbenv.set_lk_max_locks(40000); - dbenv.set_lk_max_objects(40000); - dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug - dbenv.set_flags(DB_AUTO_COMMIT, 1); - dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); - dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); - int ret = dbenv.open(strPath.c_str(), + dbenv->set_lg_dir(pathLogDir.string().c_str()); + dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet + dbenv->set_lg_bsize(0x10000); + dbenv->set_lg_max(1048576); + dbenv->set_lk_max_locks(40000); + dbenv->set_lk_max_objects(40000); + dbenv->set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug + dbenv->set_flags(DB_AUTO_COMMIT, 1); + dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); + dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); + int ret = dbenv->open(strPath.c_str(), DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -117,14 +126,14 @@ void CDBEnv::MakeMock() LogPrint("db", "CDBEnv::MakeMock\n"); - dbenv.set_cachesize(1, 0, 1); - dbenv.set_lg_bsize(10485760 * 4); - dbenv.set_lg_max(10485760); - dbenv.set_lk_max_locks(10000); - dbenv.set_lk_max_objects(10000); - dbenv.set_flags(DB_AUTO_COMMIT, 1); - dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); - int ret = dbenv.open(NULL, + dbenv->set_cachesize(1, 0, 1); + dbenv->set_lg_bsize(10485760 * 4); + dbenv->set_lg_max(10485760); + dbenv->set_lk_max_locks(10000); + dbenv->set_lk_max_objects(10000); + dbenv->set_flags(DB_AUTO_COMMIT, 1); + dbenv->log_set_config(DB_LOG_IN_MEMORY, 1); + int ret = dbenv->open(NULL, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -145,7 +154,7 @@ CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDB LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); - Db db(&dbenv, 0); + Db db(dbenv, 0); int result = db.verify(strFile.c_str(), NULL, NULL, 0); if (result == 0) return VERIFY_OK; @@ -168,7 +177,7 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vectortxn_checkpoint(0, 0, 0); if (fMockDb) return; - dbenv.lsn_reset(strFile.c_str(), 0); + dbenv->lsn_reset(strFile.c_str(), 0); } @@ -237,7 +246,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activ ++bitdb.mapFileUseCount[strFile]; pdb = bitdb.mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(&bitdb.dbenv, 0); + pdb = new Db(bitdb.dbenv, 0); bool fMockDb = bitdb.IsMock(); if (fMockDb) { @@ -284,7 +293,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); + bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -323,7 +332,7 @@ bool CDBEnv::RemoveDb(const string& strFile) this->CloseDb(strFile); LOCK(cs_db); - int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); + int rc = dbenv->dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); return (rc == 0); } @@ -343,7 +352,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(&bitdb.dbenv, 0); + Db* pdbCopy = new Db(bitdb.dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -393,10 +402,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } } if (fSuccess) { - Db dbA(&bitdb.dbenv, 0); + Db dbA(bitdb.dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(&bitdb.dbenv, 0); + Db dbB(bitdb.dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } @@ -428,12 +437,12 @@ void CDBEnv::Flush(bool fShutdown) if (nRefCount == 0) { // Move log data to the dat file CloseDb(strFile); - LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile); - dbenv.txn_checkpoint(0, 0, 0); - LogPrint("db", "CDBEnv::Flush : %s detach\n", strFile); + LogPrint("db", "CDBEnv::Flush: %s checkpoint\n", strFile); + dbenv->txn_checkpoint(0, 0, 0); + LogPrint("db", "CDBEnv::Flush: %s detach\n", strFile); if (!fMockDb) - dbenv.lsn_reset(strFile.c_str(), 0); - LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile); + dbenv->lsn_reset(strFile.c_str(), 0); + LogPrint("db", "CDBEnv::Flush: %s closed\n", strFile); mapFileUseCount.erase(mi++); } else mi++; @@ -442,7 +451,7 @@ void CDBEnv::Flush(bool fShutdown) if (fShutdown) { char** listp; if (mapFileUseCount.empty()) { - dbenv.log_archive(&listp, DB_ARCH_REMOVE); + dbenv->log_archive(&listp, DB_ARCH_REMOVE); Close(); if (!fMockDb) boost::filesystem::remove_all(boost::filesystem::path(strPath) / "database"); diff --git a/src/wallet/db.h b/src/wallet/db.h index 2128c04349c0c..756150513c631 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -43,12 +43,14 @@ class CDBEnv public: mutable CCriticalSection cs_db; - DbEnv dbenv; + DbEnv *dbenv; std::map mapFileUseCount; std::map mapDb; CDBEnv(); ~CDBEnv(); + void Reset(); + void MakeMock(); bool IsMock() { return fMockDb; } @@ -83,7 +85,7 @@ class CDBEnv DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { DbTxn* ptxn = NULL; - int ret = dbenv.txn_begin(NULL, &ptxn, flags); + int ret = dbenv->txn_begin(NULL, &ptxn, flags); if (!ptxn || ret != 0) return NULL; return ptxn; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 0dbecca824a31..24bf30b7cc0c6 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -10,6 +10,7 @@ #include #include +#include "test_pivx.h" // how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles #define RUN_TESTS 100 @@ -22,7 +23,7 @@ using namespace std; typedef set > CoinSet; -BOOST_AUTO_TEST_SUITE(wallet_tests) +BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup) static CWallet wallet; static vector vCoins; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 6dab26ae35487..566b9e4220705 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1113,8 +1113,8 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) int64_t now = GetTime(); std::string newFilename = strprintf("wallet.%d.bak", now); - int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL, - newFilename.c_str(), DB_AUTO_COMMIT); + int result = dbenv.dbenv->dbrename(NULL, filename.c_str(), NULL, + newFilename.c_str(), DB_AUTO_COMMIT); if (result == 0) LogPrintf("Renamed %s to %s\n", filename, newFilename); else { @@ -1131,12 +1131,12 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); bool fSuccess = allOK; - boost::scoped_ptr pdbCopy(new Db(&dbenv.dbenv, 0)); - int ret = pdbCopy->open(NULL, // Txn pointer - filename.c_str(), // Filename - "main", // Logical db name - DB_BTREE, // Database type - DB_CREATE, // Flags + boost::scoped_ptr pdbCopy(new Db(dbenv.dbenv, 0)); + int ret = pdbCopy->open(NULL, // Txn pointer + filename.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags 0); if (ret > 0) { LogPrintf("Cannot create database file %s\n", filename);