From 92a0f7e58d4b6323d21f1c45d4c20266c35df030 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Fri, 8 Oct 2021 18:11:40 +0200 Subject: [PATCH] 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 ``` --- src/bench/bench.cpp | 2 ++ src/qt/test/test_main.cpp | 3 +++ src/test/README.md | 28 ++++++++++++++++++++-------- src/test/fuzz/fuzz.cpp | 3 +++ src/test/main.cpp | 15 +++++++++++++++ src/test/util/setup_common.cpp | 13 +++++++++---- src/test/util/setup_common.h | 4 ++++ 7 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index f696396e12e..d7b4228566f 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -19,6 +19,8 @@ using namespace std::chrono_literals; const std::function G_TEST_LOG_FUN{}; +const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS{}; + namespace { void GenerateTemplateResults(const std::vector& benchmarkResults, const std::string& filename, const char* tpl) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 11aa61c7fc2..10b7e2ffe78 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(QT_STATICPLUGIN) #include @@ -43,6 +44,8 @@ using node::NodeContext; const std::function G_TEST_LOG_FUN{}; +const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS{}; + // This is all you need to run all the tests int main(int argc, char* argv[]) { diff --git a/src/test/README.md b/src/test/README.md index d03411c3eda..90d0e7102d0 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -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 diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index a33297e0ed7..1c994a53cfb 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,8 @@ const std::function G_TEST_LOG_FUN{}; +const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS{}; + std::map>& FuzzTargets() { static std::map> g_fuzz_targets; diff --git a/src/test/main.cpp b/src/test/main.cpp index 58855640747..1ad8fcce3ae 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -11,6 +11,7 @@ #include +#include #include /** Redirect debug log to unit_test.log files */ @@ -24,3 +25,17 @@ const std::function 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()> G_TEST_COMMAND_LINE_ARGUMENTS = []() { + std::vector 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; +}; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 87546f45f29..b41c2aa12f4 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -42,6 +42,7 @@ #include #include +#include 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 arguments = Cat( + std::vector 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(); diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 58ffd77995e..a1b7525cf45 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -19,12 +19,16 @@ #include #include +#include #include #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; +/** Retrieve the command line arguments. */ +extern const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS; + // Enable BOOST_CHECK_EQUAL for enum class types namespace std { template