test: parse the command line arguments in unit tests

Retrieve the command line arguments from boost and pass them to
`BasicTestingSetup` so that we gain extra flexibility of passing any
config options on the test command line, e.g.:

```
test_bitcoin -- -printtoconsole=1 -checkaddrman=5
```
This commit is contained in:
Vasil Dimov 2021-10-08 18:11:40 +02:00
parent c561f2f06e
commit 92a0f7e58d
No known key found for this signature in database
GPG Key ID: 54DF06F64B55CBBF
7 changed files with 56 additions and 12 deletions

View File

@ -19,6 +19,8 @@ using namespace std::chrono_literals;
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
namespace {
void GenerateTemplateResults(const std::vector<ankerl::nanobench::Result>& benchmarkResults, const std::string& filename, const char* tpl)

View File

@ -22,6 +22,7 @@
#include <QApplication>
#include <QObject>
#include <QTest>
#include <functional>
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
@ -43,6 +44,8 @@ using node::NodeContext;
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
// This is all you need to run all the tests
int main(int argc, char* argv[])
{

View File

@ -33,19 +33,31 @@ the `src/qt/test/test_main.cpp` file.
### Running individual tests
`test_bitcoin` has some built-in command-line arguments; for
example, to run just the `getarg_tests` verbosely:
`test_bitcoin` accepts the command line arguments from the boost framework.
For example, to run just the `getarg_tests` suite of tests:
test_bitcoin --log_level=all --run_test=getarg_tests -- DEBUG_LOG_OUT
```bash
test_bitcoin --log_level=all --run_test=getarg_tests
```
`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
test case is entered, for example. `test_bitcoin` also accepts the command
line arguments accepted by `bitcoind`. Use `--` to separate both types of
arguments:
```bash
test_bitcoin --log_level=all --run_test=getarg_tests -- -printtoconsole=1
```
The `-printtoconsole=1` 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:
test_bitcoin --run_test=getarg_tests/doubledash
```bash
test_bitcoin --run_test=getarg_tests/doubledash
```
Run `test_bitcoin --help` for the full list.
@ -68,7 +80,7 @@ on failure. For running individual tests verbosely, refer to the section
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_bitcoin` executable with `gdb`or `lldb` and
For debugging you can launch the `test_bitcoin` executable with `gdb` or `lldb` and
start debugging, just like you would with any other program:
```bash
@ -95,7 +107,7 @@ Running the tests and hitting a segmentation fault should now produce a file cal
`/proc/sys/kernel/core_pattern`).
You can then explore the core dump using
``` bash
```bash
gdb src/test/test_bitcoin core
(gbd) bt # produce a backtrace for where a segfault occurred

View File

@ -12,6 +12,7 @@
#include <cstdint>
#include <exception>
#include <functional>
#include <memory>
#include <string>
#include <unistd.h>
@ -19,6 +20,8 @@
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>>& FuzzTargets()
{
static std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>> g_fuzz_targets;

View File

@ -11,6 +11,7 @@
#include <test/util/setup_common.h>
#include <functional>
#include <iostream>
/** Redirect debug log to unit_test.log files */
@ -24,3 +25,17 @@ const std::function<void(const std::string&)> G_TEST_LOG_FUN = [](const std::str
if (!should_log) return;
std::cout << s;
};
/**
* Retrieve the command line arguments from boost.
* Allows usage like:
* `test_bitcoin --run_test="net_tests/cnode_listen_port" -- -checkaddrman=1 -printtoconsole=1`
* which would return `["-checkaddrman=1", "-printtoconsole=1"]`.
*/
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS = []() {
std::vector<const char*> args;
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) {
args.push_back(boost::unit_test::framework::master_test_suite().argv[i]);
}
return args;
};

View File

@ -42,6 +42,7 @@
#include <walletinitinterface.h>
#include <functional>
#include <stdexcept>
using node::BlockAssembler;
using node::CalculateCacheSizes;
@ -88,7 +89,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
m_args{}
{
m_node.args = &gArgs;
const std::vector<const char*> arguments = Cat(
std::vector<const char*> arguments = Cat(
{
"dummy",
"-printtoconsole=0",
@ -100,6 +101,9 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
"-debugexclude=leveldb",
},
extra_args);
if (G_TEST_COMMAND_LINE_ARGUMENTS) {
arguments = Cat(arguments, G_TEST_COMMAND_LINE_ARGUMENTS());
}
util::ThreadRename("test");
fs::create_directories(m_path_root);
m_args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
@ -108,9 +112,10 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
{
SetupServerArgs(*m_node.args);
std::string error;
const bool success{m_node.args->ParseParameters(arguments.size(), arguments.data(), error)};
assert(success);
assert(error.empty());
if (!m_node.args->ParseParameters(arguments.size(), arguments.data(), error)) {
m_node.args->ClearArgs();
throw std::runtime_error{error};
}
}
SelectParams(chainName);
SeedInsecureRand();

View File

@ -19,12 +19,16 @@
#include <util/string.h>
#include <util/vector.h>
#include <functional>
#include <type_traits>
#include <vector>
/** This is connected to the logger. Can be used to redirect logs to any other log */
extern const std::function<void(const std::string&)> G_TEST_LOG_FUN;
/** Retrieve the command line arguments. */
extern const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS;
// Enable BOOST_CHECK_EQUAL for enum class types
namespace std {
template <typename T>