Files
bitcoin/src/qt/test/test_main.cpp
Ava Chow 5ebb406357 Merge bitcoin/bitcoin#26564: test: test_bitcoin: allow -testdatadir=<datadir>
d27e2d87b9 test: test_bitcoin: allow -testdatadir=<datadir> (Larry Ruane)

Pull request description:

  This backward-compatible change would help with code review, testing, and debugging. When `test_bitcoin` runs, it creates a working or data directory within `/tmp/test_common_Bitcoin\ Core/`, named as a long random (hex) string.

  This small patch does three things:

  - If the (new) argument `-testdatadir=<datadir>` is given, use `<datadir>/test_temp/<test-name>/datadir` as the working directory
  - When the test starts, remove `<datadir>/test_temp/<test-name>/datadir` if it exists from an earlier run (currently, it's presumed not to exist due to the long random string)
  - Don't delete the working directory at the end of the test if a custom data directory is being used

  Example usage, which will remove, create, use `/somewhere/test_temp/getarg_tests/boolarg`, and leave it afterward:
  ```
  $ test_bitcoin --run_test=getarg_tests/boolarg -- -testdatadir=/somewhere
  Running 1 test case...
  Test directory (will not be deleted): "/somewhere/test_temp/getarg_tests/boolarg/datadir"

  *** No errors detected
  $ ls -l /somewhere/test_temp/getarg_tests/boolarg/datadir
  total 8
  drwxrwxr-x 2 larry larry 4096 Feb 22 10:28 blocks
  -rw-rw-r-- 1 larry larry 1273 Feb 22 10:28 debug.log
  ```
  (A relative pathname also works.)

  This change affects only `test_bitcoin`; it could also be applied to `test_bitcoin-qt` but that's slightly more involved so I'm skipping that for now.

  The rationale for this change is that, when running the test using the debugger, it's often useful to watch `debug.log` as the test runs and inspect some of the other files (I've looked at the generated `blknnnn.dat` files for example). Currently, that requires figuring out where the test's working directory is since it changes on every test run. Tests can be run with `-printtoconsole=1` to show debug logging to the terminal, but it's nice to keep `debug.log` continuously open in an editor, for example.

  Even if not using a debugger, it's sometimes helpful to see `debug.log` and other artifacts after the test completes.

  Similar functionality is already possible with the functional tests using the `--tmpdir=` and `--nocleanup` arguments.

ACKs for top commit:
  davidgumberg:
    ACK d27e2d87b9
  tdb3:
    re-ACK for d27e2d87b9
  achow101:
    ACK d27e2d87b9
  cbergqvist:
    ACK d27e2d87b95b7982c05b4c88e463cc9626ab9f0a! (Already did some testing with `fs::remove()` to make sure it was compatible with the `util::Lock/UnlockDirectory` implementation).
  marcofleon:
    ACK d27e2d87b9. I ran all the tests with my previous open file limit and no errors were detected. Also ran some individual tests with no, relative, and absolute paths and everything looks good.
  furszy:
    ACK d27e2d8

Tree-SHA512: a8f535f34a48b6699cb440f97f5562ec643f3bfba4ea685768980b871fc8b6e1135f70fc05dbe19aa2c8bacb1ddeaff212d63473605a7422ff76332b3a6b1f68
2024-03-11 07:03:02 -04:00

132 lines
3.9 KiB
C++

// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
#include <interfaces/init.h>
#include <interfaces/node.h>
#include <qt/bitcoin.h>
#include <qt/guiconstants.h>
#include <qt/test/apptests.h>
#include <qt/test/optiontests.h>
#include <qt/test/rpcnestedtests.h>
#include <qt/test/uritests.h>
#include <test/util/setup_common.h>
#include <util/chaintype.h>
#ifdef ENABLE_WALLET
#include <qt/test/addressbooktests.h>
#include <qt/test/wallettests.h>
#endif // ENABLE_WALLET
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QSettings>
#include <QTest>
#include <functional>
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
#if defined(QT_QPA_PLATFORM_MINIMAL)
Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin);
#endif
#if defined(QT_QPA_PLATFORM_XCB)
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_WINDOWS)
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_COCOA)
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_ANDROID)
Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
#endif
#endif
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
const std::function<std::string()> G_TEST_GET_FULL_NAME{};
// This is all you need to run all the tests
int main(int argc, char* argv[])
{
// Initialize persistent globals with the testing setup state for sanity.
// E.g. -datadir in gArgs is set to a temp directory dummy value (instead
// of defaulting to the default datadir), or globalChainParams is set to
// regtest params.
//
// All tests must use their own testing setup (if needed).
fs::create_directories([] {
BasicTestingSetup dummy{ChainType::REGTEST};
return gArgs.GetDataDirNet() / "blocks";
}());
std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
gArgs.ForceSetArg("-listen", "0");
gArgs.ForceSetArg("-listenonion", "0");
gArgs.ForceSetArg("-discover", "0");
gArgs.ForceSetArg("-dnsseed", "0");
gArgs.ForceSetArg("-fixedseeds", "0");
gArgs.ForceSetArg("-upnp", "0");
gArgs.ForceSetArg("-natpmp", "0");
std::string error;
if (!gArgs.ReadConfigFiles(error, true)) QWARN(error.c_str());
// Prefer the "minimal" platform for the test instead of the normal default
// platform ("xcb", "windows", or "cocoa") so tests can't unintentionally
// interfere with any background GUIs and don't require extra resources.
#if defined(WIN32)
if (getenv("QT_QPA_PLATFORM") == nullptr) _putenv_s("QT_QPA_PLATFORM", "minimal");
#else
setenv("QT_QPA_PLATFORM", "minimal", 0 /* overwrite */);
#endif
QCoreApplication::setOrganizationName(QAPP_ORG_NAME);
QCoreApplication::setApplicationName(QAPP_APP_NAME_DEFAULT "-test");
int num_test_failures{0};
{
BitcoinApplication app;
app.createNode(*init);
AppTests app_tests(app);
num_test_failures += QTest::qExec(&app_tests);
OptionTests options_tests(app.node());
num_test_failures += QTest::qExec(&options_tests);
URITests test1;
num_test_failures += QTest::qExec(&test1);
RPCNestedTests test3(app.node());
num_test_failures += QTest::qExec(&test3);
#ifdef ENABLE_WALLET
WalletTests test5(app.node());
num_test_failures += QTest::qExec(&test5);
AddressBookTests test6(app.node());
num_test_failures += QTest::qExec(&test6);
#endif
if (num_test_failures) {
qWarning("\nFailed tests: %d\n", num_test_failures);
} else {
qDebug("\nAll tests passed.\n");
}
}
QSettings settings;
settings.clear();
return num_test_failures;
}