diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index 5b73a1cd74..98a1a24b28 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import sys import re diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 3290a8e55b..e9eea42b96 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -20,6 +20,8 @@ EXCLUDE = [ 'src/qt/bitcoinstrings.cpp', 'src/chainparamsseeds.h', # other external copyrights: + 'src/reverse_iterator.h', + 'src/test/fuzz/FuzzedDataProvider.h', 'src/tinyformat.h', 'src/bench/nanobench.h', 'test/functional/test_framework/bignum.py', @@ -459,14 +461,14 @@ CPP_HEADER = ''' def get_cpp_header_lines_to_insert(start_year, end_year): return reversed(get_header_lines(CPP_HEADER, start_year, end_year)) -PYTHON_HEADER = ''' +SCRIPT_HEADER = ''' # Copyright (c) %s The Dash Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' -def get_python_header_lines_to_insert(start_year, end_year): - return reversed(get_header_lines(PYTHON_HEADER, start_year, end_year)) +def get_script_header_lines_to_insert(start_year, end_year): + return reversed(get_header_lines(SCRIPT_HEADER, start_year, end_year)) ################################################################################ # query git for year of last change @@ -495,17 +497,18 @@ def file_has_hashbang(file_lines): return False return file_lines[0][:2] == '#!' -def insert_python_header(filename, file_lines, start_year, end_year): +def insert_script_header(filename, file_lines, start_year, end_year): if file_has_hashbang(file_lines): insert_idx = 1 else: insert_idx = 0 - header_lines = get_python_header_lines_to_insert(start_year, end_year) + header_lines = get_script_header_lines_to_insert(start_year, end_year) for line in header_lines: file_lines.insert(insert_idx, line) write_file_lines(filename, file_lines) def insert_cpp_header(filename, file_lines, start_year, end_year): + file_lines.insert(0, '\n') header_lines = get_cpp_header_lines_to_insert(start_year, end_year) for line in header_lines: file_lines.insert(0, line) @@ -517,8 +520,8 @@ def exec_insert_header(filename, style): sys.exit('*** %s already has a copyright by The Dash Core developers' % (filename)) start_year, end_year = get_git_change_year_range(filename) - if style == 'python': - insert_python_header(filename, file_lines, start_year, end_year) + if style in ['python', 'shell']: + insert_script_header(filename, file_lines, start_year, end_year) else: insert_cpp_header(filename, file_lines, start_year, end_year) @@ -559,11 +562,13 @@ def insert_cmd(argv): if not os.path.isfile(filename): sys.exit("*** bad filename: %s" % filename) _, extension = os.path.splitext(filename) - if extension not in ['.h', '.cpp', '.cc', '.c', '.py']: + if extension not in ['.h', '.cpp', '.cc', '.c', '.py', '.sh']: sys.exit("*** cannot insert for file extension %s" % extension) if extension == '.py': style = 'python' + elif extension == '.sh': + style = 'shell' else: style = 'cpp' exec_insert_header(filename, style) diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh index 0f6afd6153..c5753e4855 100755 --- a/contrib/devtools/gen-manpages.sh +++ b/contrib/devtools/gen-manpages.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright (c) 2016-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. export LC_ALL=C TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} diff --git a/contrib/filter-lcov.py b/contrib/filter-lcov.py index df1db76e92..75034616f7 100755 --- a/contrib/filter-lcov.py +++ b/contrib/filter-lcov.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2017-2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import argparse diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py index 4fbd7416bc..9b599e52fb 100755 --- a/contrib/gitian-build.py +++ b/contrib/gitian-build.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2018-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import argparse import os diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 76f04233bc..34933ec09d 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -95,7 +95,6 @@ code. - `nullptr` is preferred over `NULL` or `(void*)0`. - `static_assert` is preferred over `assert` where possible. Generally; compile-time checking is preferred over run-time checking. - Align pointers and references to the left i.e. use `type& var` and not `type &var`. - - `enum class` is preferred over `enum` where possible. Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to int, and name clashes due to enumerators being exported to the surrounding scope. Block style example: ```c++ @@ -257,6 +256,7 @@ $ valgrind --suppressions=contrib/valgrind.supp src/test/test_dash $ valgrind --suppressions=contrib/valgrind.supp --leak-check=full \ --show-leak-kinds=all src/test/test_dash --log_level=test_suite $ valgrind -v --leak-check=full src/dashd -printtoconsole +$ ./test/functional/test_runner.py --valgrind ``` ### Compiling for test coverage @@ -582,6 +582,34 @@ class A int. If the signed int is some negative `N`, it'll become `INT_MAX - N` which might cause unexpected consequences. +- Prefer `enum class` (scoped enumerations) over `enum` (traditional enumerations) where possible. + + - *Rationale*: Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to `int`, and name clashes due to enumerators being exported to the surrounding scope. + +- `switch` statement on an enumeration example: + +```cpp +enum class Tabs { + INFO, + CONSOLE, + GRAPH, + PEERS +}; + +int GetInt(Tabs tab) +{ + switch (tab) { + case Tabs::INFO: return 0; + case Tabs::CONSOLE: return 1; + case Tabs::GRAPH: return 2; + case Tabs::PEERS: return 3; + } // no default case, so the compiler can warn about missing cases + assert(false); +} +``` + +*Rationale*: The comment documents skipping `default:` label, and it complies with `clang-format` rules. The assertion prevents firing of `-Wreturn-type` warning on some compilers. + Strings and formatting ------------------------ diff --git a/doc/files.md b/doc/files.md index e99c137359..ae05693e75 100644 --- a/doc/files.md +++ b/doc/files.md @@ -1,27 +1,107 @@ +# Dash Core file system + +**Contents** + +- [Data directory location](#data-directory-location) + +- [Data directory layout](#data-directory-layout) + +- [Multi-wallet environment](#multi-wallet-environment) + +- [GUI settings](#gui-settings) + +- [Legacy subdirectories and files](#legacy-subdirectories-and-files) + +- [Notes](#notes) + +## Data directory location + +The data directory is the default location where the Dash Core files are stored. + +1. The default data directory paths for supported platforms are: + +Platform | Data directory path +---------|-------------------- +Linux | `$HOME/.dashcore/` +macOS | `$HOME/Library/Application Support/Dashcore/` +Windows | `%APPDATA%\Dashcore\` [\[1\]](#note1) + +2. The non-default data directory path can be specified by `-datadir` option. + +3. All content of the data directory, except for `dash.conf` file, is chain-specific. This means the actual data directory paths for non-mainnet cases differ: + +Chain option | Data directory path +--------------------|-------------------- +no option (mainnet) | *path_to_datadir*`/` +`-testnet` | *path_to_datadir*`/testnet3/` +`-regtest` | *path_to_datadir*`/regtest/` + +## Data directory layout + +Subdirectory | File(s) | Description +-------------------|-----------------------|------------ +`blocks/` | | Blocks directory; can be specified by `-blocksdir` option (except for `blocks/index/`) +`blocks/index/` | LevelDB database | Block index; `-blocksdir` option does not affect this path +`blocks/` | `blkNNNNN.dat`[\[2\]](#note2) | Actual Dash blocks (in network format, dumped in raw on disk, 128 MiB per file) +`blocks/` | `revNNNNN.dat`[\[2\]](#note2) | Block undo data (custom format) +`chainstate/` | LevelDB database | Blockchain state (a compact representation of all currently unspent transaction outputs and some metadata about the transactions they are from) +`indexes/txindex/` | LevelDB database | Transaction index; *optional*, used if `-txindex=1` +`indexes/blockfilter/basic/db/` | LevelDB database | Blockfilter index LevelDB database for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`indexes/blockfilter/basic/` | `fltrNNNNN.dat`[\[2\]](#note2) | Blockfilter index filters for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`wallets/` | | [Contains wallets](#multi-wallet-environment); can be specified by `-walletdir` option; if `wallets/` subdirectory does not exist, a wallet resides in the data directory +`evodb/` | |special txes and quorums database +`llmq/` | |quorum signatures database +`./` | `banlist.dat` | Stores the IPs/subnets of banned nodes +`./` | `dash.conf` | Contains [configuration settings](dash-conf.md) for `dashd` or `dash-qt`; can be specified by `-conf` option +`./` | `dashd.pid` | Stores the process ID (PID) of `dashd` or `dash-qt` while running; created at start and deleted on shutdown; can be specified by `-pid` option +`./` | `debug.log` | Contains debug information and general logging generated by `dashd` or `dash-qt`; can be specified by `-debuglogfile` option +`./` | `governance.dat` | stores data for governance objects +`./` | `mncache.dat` | stores data for masternode list +`./` | `netfulfilled.dat` | stores data about recently made network requests +`./` | `fee_estimates.dat` | Stores statistics used to estimate minimum transaction fees and priorities required for confirmation +`./` | `guisettings.ini.bak` | Backup of former [GUI settings](#gui-settings) after `-resetguisettings` option is used +`./` | `mempool.dat` | Dump of the mempool's transactions +`./` | `onion_v3_private_key` | Cached Tor hidden service private key for `-listenonion` option +`./` | `peers.dat` | Peer IP address database (custom format) +`./` | `.cookie` | Session RPC authentication cookie; if used, created at start and deleted on shutdown; can be specified by `-rpccookiefile` option +`./` | `.lock` | Data directory lock file + +## Multi-wallet environment + +Wallets are Berkeley DB (BDB) databases: + +Subdirectory | File(s) | Description +-------------|-------------------|------------ +`database/` | BDB logging files | Part of BDB environment; created at start and deleted on shutdown; a user *must keep it as safe* as personal wallet `wallet.dat` +`./` | `db.log` | BDB error file +`./` | `wallet.dat` | Personal wallet (BDB) with keys and transactions +`./` | `.walletlock` | Wallet lock file + +1. Each user-defined wallet named "wallet_name" resides in `wallets/wallet_name/` subdirectory. + +2. The default (unnamed) wallet resides in `wallets/` subdirectory; if the latter does not exist, the wallet resides in the data directory. + +3. A wallet database path can be specified by `-wallet` option. + +## GUI settings + +`dash-qt` uses [`QSettings`](https://doc.qt.io/qt-5/qsettings.html) class; this implies platform-specific [locations where application settings are stored](https://doc.qt.io/qt-5/qsettings.html#locations-where-application-settings-are-stored). + +## Legacy subdirectories and files + +These subdirectories and files are no longer used by the Dash Core: + +Path | Description | Repository notes +---------------|-------------|----------------- +`blktree/` | Blockchain index; replaced by `blocks/index/` in [0.8.0](https://github.com/dash/dash/blob/master/doc/release-notes/release-notes-0.8.0.md#improvements) | [PR #2231](https://github.com/dash/dash/pull/2231), [`8fdc94cc`](https://github.com/dash/dash/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`coins/` | Unspent transaction output database; replaced by `chainstate/` in 0.8.0 | [PR #2231](https://github.com/dash/dash/pull/2231), [`8fdc94cc`](https://github.com/dash/dash/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`blkindex.dat` | Blockchain index BDB database; replaced by {`chainstate/`, `blocks/index/`, `blocks/revNNNNN.dat`[\[2\]](#note2)} in 0.8.0 | [PR #1677](https://github.com/dash/dash/pull/1677) +`blk000?.dat` | Block data (custom format, 2 GiB per file); replaced by `blocks/blkNNNNN.dat`[\[2\]](#note2) in 0.8.0 | [PR #1677](https://github.com/dash/dash/pull/1677) +`addr.dat` | Peer IP address BDB database; replaced by `peers.dat` in [0.7.0](https://github.com/dash/dash/blob/master/doc/release-notes/release-notes-0.7.0.md) | [PR #1198](https://github.com/dash/dash/pull/1198), [`928d3a01`](https://github.com/dash/dash/commit/928d3a011cc66c7f907c4d053f674ea77dc611cc) + +## Notes + +1. The `/` (slash, U+002F) is used as the platform-independent path component separator in this paper. + +2. `NNNNN` matches `[0-9]{5}` regex. -* banlist.dat: stores the IPs/Subnets of banned nodes -* blocks/blk000??.dat: block data (custom, 128 MiB per file) -* blocks/rev000??.dat; block undo data (custom) -* blocks/index/*; block index (LevelDB) -* chainstate/*; block chain state database (LevelDB) -* dash.conf: contains configuration settings for dashd or dash-qt -* dashd.pid: stores the process id of dashd while running -* database/*: BDB database environment; only used for wallet; moved to wallets/ directory on new installs since 0.16.0 -* db.log: wallet database log file; moved to wallets/ directory on new installs since 0.16.0 -* debug.log: contains debug information and general logging generated by dashd or dash-qt -* evodb/*: special txes and quorums database -* fee_estimates.dat: stores statistics used to estimate minimum transaction fees and priorities required for confirmation -* governance.dat: stores data for governance objects -* indexes/txindex/*: optional transaction index database (LevelDB); since 0.17.0 -* llmq/*: quorum signatures database -* mempool.dat: dump of the mempool's transactions -* mncache.dat: stores data for masternode list -* netfulfilled.dat: stores data about recently made network requests -* peers.dat: peer IP address database (custom format) -* wallet.dat: personal wallet (BDB) with keys and transactions; moved to wallets/ directory on new installs since 0.16.0 -* wallets/database/*: BDB database environment; used for wallets since 0.16.0 -* wallets/db.log: wallet database log file; since 0.16.0 -* wallets/wallet.dat: personal wallet (BDB) with keys and transactions; since 0.16.0 -* .cookie: session RPC authentication cookie (written at start when cookie authentication is used, deleted on shutdown) -* onion_v3_private_key: cached Tor hidden service private key for `-listenonion` -* guisettings.ini.bak: backup of former GUI settings after `-resetguisettings` is used diff --git a/src/.clang-format b/src/.clang-format index bedf672b61..7e649de43f 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -5,6 +5,7 @@ AlignEscapedNewlinesLeft: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 6e93cc05a5..ed9db7f04e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -686,7 +686,7 @@ endif %.cpp.test: %.cpp @echo Running tests: `cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $< - $(AM_V_at)$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" > $<.log 2>&1 || (cat $<.log && false) + $(AM_V_at)$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" -- DEBUG_LOG_OUT > $<.log 2>&1 || (cat $<.log && false) test/data/%.json.h: test/data/%.json @$(MKDIR_P) $(@D) diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index f26d6fc7b8..3e251ed15d 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -13,6 +13,7 @@ #include #include +const std::function G_TEST_LOG_FUN{}; namespace { void GenerateTemplateResults(const std::vector& benchmarkResults, const std::string& filename, const char* tpl) diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp index 90a72516a4..624bdb42e4 100644 --- a/src/crypto/sha256_avx2.cpp +++ b/src/crypto/sha256_avx2.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifdef ENABLE_AVX2 #include diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp index fc79f46f7f..4eaf7d7b18 100644 --- a/src/crypto/sha256_sse41.cpp +++ b/src/crypto/sha256_sse41.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifdef ENABLE_SSE41 #include diff --git a/src/fs.cpp b/src/fs.cpp index 9f19dfd52f..5a75c6317e 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #ifndef WIN32 diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index a4c513f9bf..1d591bf196 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h index beeb9e76a9..aa1b2f20b0 100644 --- a/src/qt/test/addressbooktests.h +++ b/src/qt/test/addressbooktests.h @@ -1,3 +1,7 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H #define BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 05ba034084..a2f55a5660 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -46,6 +46,8 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); #endif #endif +const std::function G_TEST_LOG_FUN{}; + // This is all you need to run all the tests int main(int argc, char *argv[]) { diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp index ae2fb93bf7..e09f0ad77d 100644 --- a/src/qt/test/util.cpp +++ b/src/qt/test/util.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include diff --git a/src/qt/test/util.h b/src/qt/test/util.h index 377f07dcba..763847606a 100644 --- a/src/qt/test/util.h +++ b/src/qt/test/util.h @@ -1,3 +1,7 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_UTIL_H #define BITCOIN_QT_TEST_UTIL_H diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 24b230fb10..57469d7843 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2015-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h index 342f7916c3..388eb9500e 100644 --- a/src/qt/test/wallettests.h +++ b/src/qt/test/wallettests.h @@ -1,3 +1,7 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_WALLETTESTS_H #define BITCOIN_QT_TEST_WALLETTESTS_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 6346190ad2..ed2feb24c9 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -623,7 +623,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)" }, RPCExamples{ - HelpExampleCli("combinerawtransaction", "'[\"myhex1\", \"myhex2\", \"myhex3\"]'") + HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") }, }.ToString()); @@ -878,7 +878,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) "Sign the transaction, and get back the hex\n" + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + "\nTest acceptance of the transaction (signed hex)\n" - + HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") + + + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") }, @@ -1205,7 +1205,7 @@ UniValue combinepsbt(const JSONRPCRequest& request) RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" }, RPCExamples{ - HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]") + HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") }, }.ToString()); diff --git a/src/test/README.md b/src/test/README.md index 05e7a8178c..e46152b7e8 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -17,26 +17,31 @@ and tests weren't explicitly disabled. After configuring, they can be run with `make check`. -To run the dashd tests manually, launch `src/test/test_dash`. To recompile +To run the unit tests manually, launch `src/test/test_dash`. To recompile after a test file was modified, run `make` and then run the test again. If you modify a non-test file, use `make -C src/test` to recompile only what's needed -to run the dashd tests. +to run the unit tests. -To add more dashd tests, add `BOOST_AUTO_TEST_CASE` functions to the existing +To add more unit tests, add `BOOST_AUTO_TEST_CASE` functions to the existing .cpp files in the `test/` directory or add new .cpp files that implement new `BOOST_AUTO_TEST_SUITE` sections. -To run the dash-qt tests manually, launch `src/qt/test/test_dash-qt` +To run the GUI unit tests manually, launch `src/qt/test/test_dash-qt` -To add more dash-qt tests, add them to the `src/qt/test/` directory and +To add more GUI unit tests, add them to the `src/qt/test/` directory and the `src/qt/test/test_main.cpp` file. ### Running individual tests -test_dash has some built-in command-line arguments; for -example, to run just the getarg_tests verbosely: +`test_dash` has some built-in command-line arguments; for +example, to run just the `getarg_tests` verbosely: - test_dash --log_level=all --run_test=getarg_tests + test_dash --log_level=all --run_test=getarg_tests -- DEBUG_LOG_OUT + +`log_level` controls the verbosity of the test framework, which logs when a +test case is entered, for example. The `DEBUG_LOG_OUT` after the two dashes +redirects the debug log, which would normally go to a file in the test datadir +(`BasicTestingSetup::m_path_root`), to the standard terminal output. ... or to run just the doubledash test: @@ -56,11 +61,15 @@ see `uint256_tests.cpp`. ### Logging and debugging in unit tests +`make check` will write to a log file `foo_tests.cpp.log` and display this file +on failure. For running individual tests verbosely, refer to the section +[above](#running-individual-tests). + To write to logs from unit tests you need to use specific message methods provided by Boost. The simplest is `BOOST_TEST_MESSAGE`. -For debugging you can launch the test_dash executable with `gdb`or `lldb` and -start debugging, just like you would with dashd: +For debugging you can launch the `test_dash` executable with `gdb`or `lldb` and +start debugging, just like you would with any other program: ```bash gdb src/test/test_dash diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 29935c09f8..65c073a13d 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2017-2019 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 5bf279f4c5..3984f68116 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -4,10 +4,14 @@ #include +#include + #include #include #include +const std::function G_TEST_LOG_FUN{}; + static bool read_stdin(std::vector& data) { uint8_t buffer[1024]; diff --git a/src/test/main.cpp b/src/test/main.cpp index 1862ee48df..3efeb827ea 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -2,6 +2,25 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/** + * See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/link_references/link_boost_test_module_macro.html + */ #define BOOST_TEST_MODULE Dash Core Test Suite #include + +#include + +#include + +/** Redirect debug log to unit_test.log files */ +const std::function G_TEST_LOG_FUN = [](const std::string& s) { + static const bool should_log{std::any_of( + &boost::unit_test::framework::master_test_suite().argv[1], + &boost::unit_test::framework::master_test_suite().argv[boost::unit_test::framework::master_test_suite().argc], + [](const char* arg) { + return std::string{"DEBUG_LOG_OUT"} == arg; + })}; + if (!should_log) return; + std::cout << s; +}; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index ef83718af1..219dab919b 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -77,6 +77,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName) SelectParams(chainName); SeedInsecureRand(); gArgs.ForceSetArg("-printtoconsole", "0"); + if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN); InitLogging(); LogInstance().StartLogging(); SHA256AutoDetect(); diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 378e2a00f6..40de4fe87a 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -19,6 +19,9 @@ #include +/** This is connected to the logger. Can be used to redirect logs to any other log */ +extern const std::function G_TEST_LOG_FUN; + // Enable BOOST_CHECK_EQUAL for enum class types template std::ostream& operator<<(typename std::enable_if::value, std::ostream>::type& stream, const T& e) diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py index 7268a5216b..22a1fbe4aa 100755 --- a/test/functional/combine_logs.py +++ b/test/functional/combine_logs.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2017-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. """Combine logs from multiple bitcoin nodes as well as the test_framework log. This streams the combined log output to stdout. Use combine_logs.py > outputfile diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index d3d80dfd10..5465415aea 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -156,6 +156,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): help="Scale the test timeouts by multiplying them with the here provided value (default: %(default)s)") parser.add_argument("--perf", dest="perf", default=False, action="store_true", help="profile running nodes with perf for the duration of the test") + parser.add_argument("--valgrind", dest="valgrind", default=False, action="store_true", + help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required") parser.add_argument("--randomseed", type=int, help="set a random seed for deterministically reproducing a previous test run") self.add_options(parser) @@ -405,6 +407,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): extra_args=extra_args[i], use_cli=self.options.usecli, start_perf=self.options.perf, + use_valgrind=self.options.valgrind, )) def start_node(self, i, *args, **kwargs): diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 098b055f5a..e3c9b566e5 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -60,7 +60,7 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False): + def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False): """ Kwargs: start_perf (bool): If True, begin profiling the node with `perf` as soon as @@ -101,6 +101,15 @@ class TestNode(): "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i ] + if use_valgrind: + default_suppressions_file = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "..", "..", "..", "contrib", "valgrind.supp") + suppressions_file = os.getenv("VALGRIND_SUPPRESSIONS_FILE", + default_suppressions_file) + self.args = ["valgrind", "--suppressions={}".format(suppressions_file), + "--gen-suppressions=all", "--exit-on-first-error=yes", + "--error-exitcode=1", "--quiet"] + self.args self.cli = TestNodeCLI(bitcoin_cli, self.datadir) self.use_cli = use_cli diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh index 1f52f13ed6..accf459c89 100755 --- a/test/lint/lint-locale-dependence.sh +++ b/test/lint/lint-locale-dependence.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright (c) 2018-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. export LC_ALL=C diff --git a/test/lint/lint-shebang.sh b/test/lint/lint-shebang.sh index fda22592d3..a666fdfecf 100755 --- a/test/lint/lint-shebang.sh +++ b/test/lint/lint-shebang.sh @@ -1,4 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) 2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # Assert expected shebang lines export LC_ALL=C