Skip to content

Commit cf03268

Browse files
committed
tests: cover qml startup helpers and chain app-name mapping (issue 02)
1 parent b813274 commit cf03268

6 files changed

Lines changed: 197 additions & 63 deletions

File tree

qml/bitcoin.cpp

Lines changed: 8 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@
44

55
#include <qml/bitcoin.h>
66

7-
#include <common/args.h>
8-
#include <common/init.h>
9-
#include <common/system.h>
107
#include <chainparams.h>
118
#include <common/args.h>
9+
#include <common/init.h>
1210
#include <common/system.h>
1311
#include <init.h>
1412
#include <interfaces/chain.h>
@@ -20,6 +18,7 @@
2018
#include <noui.h>
2119
#include <qml/appmode.h>
2220
#include <qml/bitcoinamount.h>
21+
#include <qml/bitcoinstartup.h>
2322
#include <qml/clipboard.h>
2423
#ifdef __ANDROID__
2524
#include <qml/androidnotifier.h>
@@ -56,6 +55,7 @@
5655
#ifdef ENABLE_TEST_AUTOMATION
5756
#include <qml/test/testbridge.h>
5857
#endif
58+
#include <util/chaintype.h>
5959
#include <util/threadnames.h>
6060
#include <util/translation.h>
6161

@@ -96,17 +96,6 @@ Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin)
9696
#endif
9797

9898
namespace {
99-
void SetupUIArgs(ArgsManager& argsman)
100-
{
101-
argsman.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
102-
argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
103-
argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
104-
argsman.AddArg("-skiponboard", "Skip onboarding flow and start directly in the main app", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
105-
#ifdef ENABLE_TEST_AUTOMATION
106-
argsman.AddArg("-test-automation=<path>", "Enable test automation bridge on the given Unix socket path", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
107-
#endif
108-
}
109-
11099
AppMode SetupAppMode()
111100
{
112101
bool wallet_enabled;
@@ -156,39 +145,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
156145
}
157146
}
158147

159-
bool ConfigurationFileExists(ArgsManager& argsman)
160-
{
161-
fs::path settings_path;
162-
if (!argsman.GetSettingsPath(&settings_path)) {
163-
// settings file is disabled
164-
return true;
165-
}
166-
if (fs::exists(settings_path)) {
167-
return true;
168-
}
169-
170-
const fs::path rel_config_path = argsman.GetPathArg("-conf", BITCOIN_CONF_FILENAME);
171-
const fs::path abs_config_path = AbsPathForConfigVal(argsman, rel_config_path, true);
172-
if (fs::exists(abs_config_path)) {
173-
return true;
174-
}
175-
176-
return false;
177-
}
178-
179-
void setupChainQSettings(QGuiApplication* app, QString chain)
180-
{
181-
if (chain.compare("MAIN") == 0) {
182-
app->setApplicationName(QAPP_APP_NAME_DEFAULT);
183-
} else if (chain.compare("TEST") == 0) {
184-
app->setApplicationName(QAPP_APP_NAME_TESTNET);
185-
} else if (chain.compare("SIGNET") == 0) {
186-
app->setApplicationName(QAPP_APP_NAME_SIGNET);
187-
} else if (chain.compare("REGTEST") == 0) {
188-
app->setApplicationName(QAPP_APP_NAME_REGTEST);
189-
}
190-
}
191-
192148
void LoadFontResource(const QString& path)
193149
{
194150
if (QFontDatabase::addApplicationFont(path) < 0) {
@@ -251,19 +207,7 @@ int QmlGuiMain(int argc, char* argv[])
251207
InitLogging(gArgs);
252208
InitParameterInteraction(gArgs);
253209

254-
QVariant need_onboarding(true);
255-
if (gArgs.IsArgSet("-datadir") && !gArgs.GetPathArg("-datadir").empty()) {
256-
need_onboarding.setValue(false);
257-
} else if (ConfigurationFileExists(gArgs)) {
258-
need_onboarding.setValue(false);
259-
}
260-
261-
if (gArgs.IsArgSet("-resetguisettings")) {
262-
need_onboarding.setValue(true);
263-
}
264-
if (gArgs.GetBoolArg("-skiponboard", false)) {
265-
need_onboarding.setValue(false);
266-
}
210+
const bool need_onboarding{ShouldShowOnboarding(gArgs, ConfigurationFileExists(gArgs))};
267211

268212
// legacy GUI: createNode()
269213
std::unique_ptr<interfaces::Node> node = init->makeNode();
@@ -300,8 +244,9 @@ int QmlGuiMain(int argc, char* argv[])
300244
#endif
301245

302246
ChainModel chain_model{*chain};
303-
chain_model.setCurrentNetworkName(QString::fromStdString(gArgs.GetChainTypeString()));
304-
setupChainQSettings(&app, chain_model.currentNetworkName());
247+
const ChainType chain_type{Params().GetChainType()};
248+
chain_model.setCurrentNetworkName(QString::fromStdString(ChainTypeToString(chain_type)));
249+
ApplyChainQSettingsApplicationName(app, chain_type);
305250

306251
QObject::connect(&node_model, &NodeModel::setTimeRatioList, &chain_model, &ChainModel::setTimeRatioList);
307252
QObject::connect(&node_model, &NodeModel::setTimeRatioListInitial, &chain_model, &ChainModel::setTimeRatioListInitial);
@@ -349,7 +294,7 @@ int QmlGuiMain(int argc, char* argv[])
349294
engine.rootContext()->setContextProperty("walletListModel", &wallet_list_model);
350295
#endif
351296

352-
OptionsQmlModel options_model(*node, !need_onboarding.toBool());
297+
OptionsQmlModel options_model(*node, !need_onboarding);
353298

354299
AppMode app_mode = SetupAppMode();
355300
DesktopWindowBehaviorModel desktop_window_behavior_model{app_mode.isDesktop()};

qml/bitcoinstartup.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) 2026 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <qml/bitcoinstartup.h>
6+
7+
#include <common/init.h>
8+
#include <common/system.h>
9+
#include <qml/guiconstants.h>
10+
11+
#include <QCoreApplication>
12+
13+
void SetupUIArgs(ArgsManager& argsman)
14+
{
15+
argsman.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
16+
argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
17+
argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
18+
argsman.AddArg("-skiponboard", "Skip onboarding flow and start directly in the main app", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
19+
#ifdef ENABLE_TEST_AUTOMATION
20+
argsman.AddArg("-test-automation=<path>", "Enable test automation bridge on the given Unix socket path", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
21+
#endif
22+
}
23+
24+
bool ConfigurationFileExists(ArgsManager& argsman)
25+
{
26+
fs::path settings_path;
27+
if (!argsman.GetSettingsPath(&settings_path)) {
28+
// Settings file is disabled.
29+
return true;
30+
}
31+
if (fs::exists(settings_path)) {
32+
return true;
33+
}
34+
35+
const fs::path rel_config_path = argsman.GetPathArg("-conf", BITCOIN_CONF_FILENAME);
36+
const fs::path abs_config_path = AbsPathForConfigVal(argsman, rel_config_path, /*net_specific=*/true);
37+
return fs::exists(abs_config_path);
38+
}
39+
40+
bool ShouldShowOnboarding(const ArgsManager& argsman, bool configuration_file_exists)
41+
{
42+
bool need_onboarding{true};
43+
44+
if (argsman.IsArgSet("-datadir") && !argsman.GetPathArg("-datadir").empty()) {
45+
need_onboarding = false;
46+
} else if (configuration_file_exists) {
47+
need_onboarding = false;
48+
}
49+
50+
if (argsman.GetBoolArg("-resetguisettings", false)) {
51+
need_onboarding = true;
52+
}
53+
if (argsman.GetBoolArg("-skiponboard", false)) {
54+
need_onboarding = false;
55+
}
56+
57+
return need_onboarding;
58+
}
59+
60+
QString ApplicationNameForChain(ChainType chain_type)
61+
{
62+
switch (chain_type) {
63+
case ChainType::MAIN:
64+
return QStringLiteral(QAPP_APP_NAME_DEFAULT);
65+
case ChainType::TESTNET:
66+
return QStringLiteral(QAPP_APP_NAME_TESTNET);
67+
case ChainType::TESTNET4:
68+
return QStringLiteral(QAPP_APP_NAME_TESTNET4);
69+
case ChainType::SIGNET:
70+
return QStringLiteral(QAPP_APP_NAME_SIGNET);
71+
case ChainType::REGTEST:
72+
return QStringLiteral(QAPP_APP_NAME_REGTEST);
73+
}
74+
75+
return QStringLiteral(QAPP_APP_NAME_DEFAULT);
76+
}
77+
78+
void ApplyChainQSettingsApplicationName(QCoreApplication& app, ChainType chain_type)
79+
{
80+
app.setApplicationName(ApplicationNameForChain(chain_type));
81+
}

qml/bitcoinstartup.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2026 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_QML_BITCOINSTARTUP_H
6+
#define BITCOIN_QML_BITCOINSTARTUP_H
7+
8+
#include <common/args.h>
9+
#include <util/chaintype.h>
10+
11+
#include <QString>
12+
13+
class QCoreApplication;
14+
15+
void SetupUIArgs(ArgsManager& argsman);
16+
bool ConfigurationFileExists(ArgsManager& argsman);
17+
bool ShouldShowOnboarding(const ArgsManager& argsman, bool configuration_file_exists);
18+
QString ApplicationNameForChain(ChainType chain_type);
19+
void ApplyChainQSettingsApplicationName(QCoreApplication& app, ChainType chain_type);
20+
21+
#endif // BITCOIN_QML_BITCOINSTARTUP_H

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_executable(bitcoinqml_unit_tests
88
test_unit_tests_main.cpp
99
test_bitcoinamount.cpp
1010
test_bitcoinaddress.cpp
11+
test_bitcoinstartup.cpp
1112
test_linegraph.cpp
1213
test_blockclockdial.cpp
1314
test_paymentrequest.cpp
@@ -45,6 +46,7 @@ add_executable(bitcoinqml_unit_tests
4546
test_transactionrbfadapter.cpp
4647
test_bip21uri.cpp
4748
${CMAKE_CURRENT_SOURCE_DIR}/../qml/bitcoinamount.cpp
49+
${CMAKE_CURRENT_SOURCE_DIR}/../qml/bitcoinstartup.cpp
4850
${CMAKE_CURRENT_SOURCE_DIR}/../qml/models/bitcoinaddress.cpp
4951
${CMAKE_CURRENT_SOURCE_DIR}/../qml/models/paymentrequest.cpp
5052
${CMAKE_CURRENT_SOURCE_DIR}/../qml/models/bip21uri.cpp

test/test_bitcoinstartup.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) 2026 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <QtTest/QtTest>
6+
7+
#include <common/args.h>
8+
#include <qml/bitcoinstartup.h>
9+
#include <qml/guiconstants.h>
10+
11+
#include <QCoreApplication>
12+
13+
class BitcoinStartupTests : public QObject
14+
{
15+
Q_OBJECT
16+
17+
private Q_SLOTS:
18+
void applicationNameForChain_matchesExpectedNetworkNames();
19+
void applyChainQSettingsApplicationName_setsQSettingsApplicationName();
20+
void shouldShowOnboarding_respectsStartupFlagPrecedence();
21+
};
22+
23+
void BitcoinStartupTests::applicationNameForChain_matchesExpectedNetworkNames()
24+
{
25+
QCOMPARE(ApplicationNameForChain(ChainType::MAIN), QStringLiteral(QAPP_APP_NAME_DEFAULT));
26+
QCOMPARE(ApplicationNameForChain(ChainType::TESTNET), QStringLiteral(QAPP_APP_NAME_TESTNET));
27+
QCOMPARE(ApplicationNameForChain(ChainType::TESTNET4), QStringLiteral(QAPP_APP_NAME_TESTNET4));
28+
QCOMPARE(ApplicationNameForChain(ChainType::SIGNET), QStringLiteral(QAPP_APP_NAME_SIGNET));
29+
QCOMPARE(ApplicationNameForChain(ChainType::REGTEST), QStringLiteral(QAPP_APP_NAME_REGTEST));
30+
}
31+
32+
void BitcoinStartupTests::applyChainQSettingsApplicationName_setsQSettingsApplicationName()
33+
{
34+
QCoreApplication* app{QCoreApplication::instance()};
35+
QVERIFY(app != nullptr);
36+
37+
const QString original_name{app->applicationName()};
38+
ApplyChainQSettingsApplicationName(*app, ChainType::TESTNET4);
39+
QCOMPARE(app->applicationName(), QStringLiteral(QAPP_APP_NAME_TESTNET4));
40+
41+
ApplyChainQSettingsApplicationName(*app, ChainType::REGTEST);
42+
QCOMPARE(app->applicationName(), QStringLiteral(QAPP_APP_NAME_REGTEST));
43+
44+
app->setApplicationName(original_name);
45+
}
46+
47+
void BitcoinStartupTests::shouldShowOnboarding_respectsStartupFlagPrecedence()
48+
{
49+
ArgsManager default_args;
50+
QVERIFY(ShouldShowOnboarding(default_args, /*configuration_file_exists=*/false));
51+
52+
ArgsManager datadir_args;
53+
datadir_args.ForceSetArg("-datadir", "/tmp/bitcoin-core-app-tests");
54+
QVERIFY(!ShouldShowOnboarding(datadir_args, /*configuration_file_exists=*/false));
55+
56+
ArgsManager config_args;
57+
QVERIFY(!ShouldShowOnboarding(config_args, /*configuration_file_exists=*/true));
58+
59+
ArgsManager reset_args;
60+
reset_args.ForceSetArg("-datadir", "/tmp/bitcoin-core-app-tests");
61+
reset_args.ForceSetArg("-resetguisettings", "1");
62+
QVERIFY(ShouldShowOnboarding(reset_args, /*configuration_file_exists=*/true));
63+
64+
ArgsManager skip_args;
65+
skip_args.ForceSetArg("-skiponboard", "1");
66+
QVERIFY(!ShouldShowOnboarding(skip_args, /*configuration_file_exists=*/false));
67+
68+
ArgsManager reset_and_skip_args;
69+
reset_and_skip_args.ForceSetArg("-resetguisettings", "1");
70+
reset_and_skip_args.ForceSetArg("-skiponboard", "1");
71+
QVERIFY(!ShouldShowOnboarding(reset_and_skip_args, /*configuration_file_exists=*/true));
72+
}
73+
74+
int RunBitcoinStartupTests(int argc, char* argv[])
75+
{
76+
BitcoinStartupTests tests;
77+
return QTest::qExec(&tests, argc, argv);
78+
}
79+
80+
#ifndef BITCOINQML_NO_TEST_MAIN
81+
QTEST_MAIN(BitcoinStartupTests)
82+
#endif
83+
#include "test_bitcoinstartup.moc"

test/test_unit_tests_main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
int RunBitcoinAmountTests(int argc, char* argv[]);
1010
int RunBitcoinAddressTests(int argc, char* argv[]);
11+
int RunBitcoinStartupTests(int argc, char* argv[]);
1112
int RunImageProviderTests(int argc, char* argv[]);
1213
int RunLineGraphTests(int argc, char* argv[]);
1314
int RunBlockClockDialTests(int argc, char* argv[]);
@@ -54,6 +55,7 @@ int main(int argc, char* argv[])
5455
int status = 0;
5556
status |= RunBitcoinAmountTests(argc, argv);
5657
status |= RunBitcoinAddressTests(argc, argv);
58+
status |= RunBitcoinStartupTests(argc, argv);
5759
status |= RunImageProviderTests(argc, argv);
5860
status |= RunLineGraphTests(argc, argv);
5961
status |= RunBlockClockDialTests(argc, argv);

0 commit comments

Comments
 (0)