diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 4e41925193670..c1ac84cacf6c8 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -268,6 +268,7 @@ BITCOIN_QT_WALLET_CPP = \
qt/transactiondesc.cpp \
qt/transactiondescdialog.cpp \
qt/transactionfilterproxy.cpp \
+ qt/transactionoverviewwidget.cpp \
qt/transactionrecord.cpp \
qt/transactiontablemodel.cpp \
qt/transactionview.cpp \
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 8022b8efcb195..8c4a950a5707f 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -8,6 +8,7 @@ TESTS += qt/test/test_dash-qt
TEST_QT_MOC_CPP = \
qt/test/moc_apptests.cpp \
+ qt/test/moc_optiontests.cpp \
qt/test/moc_rpcnestedtests.cpp \
qt/test/moc_trafficgraphdatatests.cpp \
qt/test/moc_uritests.cpp
@@ -21,6 +22,7 @@ endif # ENABLE_WALLET
TEST_QT_H = \
qt/test/addressbooktests.h \
qt/test/apptests.h \
+ qt/test/optiontests.h \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
qt/test/util.h \
@@ -32,6 +34,7 @@ qt_test_test_dash_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_
qt_test_test_dash_qt_SOURCES = \
qt/test/apptests.cpp \
+ qt/test/optiontests.cpp \
qt/test/rpcnestedtests.cpp \
qt/test/test_main.cpp \
qt/test/trafficgraphdatatests.cpp \
@@ -55,7 +58,7 @@ if ENABLE_ZMQ
qt_test_test_dash_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_test_test_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBDASHBLS) $(LIBUNIVALUE) $(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BACKTRACE_LIB) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
+ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BACKTRACE_LIB) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
$(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(GMP_LIBS)
qt_test_test_dash_qt_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index e6e75ae37f19c..472fbd7bdd0bb 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -68,6 +68,8 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
#elif defined(QT_QPA_PLATFORM_COCOA)
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
Q_IMPORT_PLUGIN(QMacStylePlugin);
+#elif defined(QT_QPA_PLATFORM_ANDROID)
+Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
#endif
#endif
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 587822dc23841..57aad51ab279c 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -175,7 +175,9 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const NetworkStyle* networkStyle,
frameBlocksLayout->addWidget(unitDisplayControl);
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelWalletHDStatusIcon);
+ labelWalletHDStatusIcon->hide();
frameBlocksLayout->addWidget(labelWalletEncryptionIcon);
+ labelWalletEncryptionIcon->hide();
}
frameBlocksLayout->addWidget(labelProxyIcon);
frameBlocksLayout->addStretch();
@@ -410,7 +412,7 @@ void BitcoinGUI::createActions()
verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Dash addresses"));
m_load_psbt_action = new QAction(tr("&Load PSBT from file…"), this);
m_load_psbt_action->setStatusTip(tr("Load Partially Signed Blockchain Transaction"));
- m_load_psbt_clipboard_action = new QAction(tr("Load PSBT from clipboard…"), this);
+ m_load_psbt_clipboard_action = new QAction(tr("Load PSBT from &clipboard…"), this);
m_load_psbt_clipboard_action->setStatusTip(tr("Load Partially Signed Blockchain Transaction from clipboard"));
openInfoAction = new QAction(tr("&Information"), this);
@@ -423,7 +425,7 @@ void BitcoinGUI::createActions()
openPeersAction->setStatusTip(tr("Show peers info"));
openRepairAction = new QAction(tr("Wallet &Repair"), this);
openRepairAction->setStatusTip(tr("Show wallet repair options"));
- openConfEditorAction = new QAction(tr("Open Wallet &Configuration File"), this);
+ openConfEditorAction = new QAction(tr("Open &wallet configuration file"), this);
openConfEditorAction->setStatusTip(tr("Open configuration file"));
// override TextHeuristicRole set by default which confuses this action with application settings
openConfEditorAction->setMenuRole(QAction::NoRole);
@@ -610,7 +612,7 @@ void BitcoinGUI::createMenuBar()
QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
- QAction* minimize_action = window_menu->addAction(tr("Minimize"));
+ QAction* minimize_action = window_menu->addAction(tr("&Minimize"));
minimize_action->setShortcut(QKeySequence(tr("Ctrl+M")));
connect(minimize_action, &QAction::triggered, [] {
QApplication::activeWindow()->showMinimized();
@@ -915,8 +917,8 @@ void BitcoinGUI::addWallet(WalletModel* walletModel)
{
if (!walletFrame) return;
- WalletView* wallet_view = new WalletView(walletFrame);
- if (!walletFrame->addWallet(walletModel, wallet_view)) return;
+ WalletView* wallet_view = new WalletView(walletModel, walletFrame);
+ if (!walletFrame->addView(wallet_view)) return;
rpcConsole->addWallet(walletModel);
if (m_wallet_selector->count() == 0) {
@@ -1874,6 +1876,12 @@ void BitcoinGUI::setEncryptionStatus(int status)
{
switch(status)
{
+ case WalletModel::NoKeys:
+ labelWalletEncryptionIcon->hide();
+ encryptWalletAction->setChecked(false);
+ changePassphraseAction->setEnabled(false);
+ encryptWalletAction->setEnabled(false);
+ break;
case WalletModel::Unencrypted:
labelWalletEncryptionIcon->show();
labelWalletEncryptionIcon->setPixmap(GUIUtil::getIcon("lock_open", GUIUtil::ThemedColor::RED).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
diff --git a/src/qt/forms/openuridialog.ui b/src/qt/forms/openuridialog.ui
index 5defbdd4e7101..8a1789dec4765 100644
--- a/src/qt/forms/openuridialog.ui
+++ b/src/qt/forms/openuridialog.ui
@@ -30,6 +30,22 @@
+ -
+
+
+ Paste address from clipboard
+
+
+
+
+
+
+ 22
+ 22
+
+
+
+
-
@@ -64,7 +80,9 @@
-
+
+
+
buttonBox
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 2574adee48212..33037b997c388 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -61,6 +61,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -512,6 +513,17 @@ QString getDefaultDataDirectory()
return PathToQString(GetDefaultDataDir());
}
+QString ExtractFirstSuffixFromFilter(const QString& filter)
+{
+ QRegularExpression filter_re(QStringLiteral(".* \\(\\*\\.(.*)[ \\)]"), QRegularExpression::InvertedGreedinessOption);
+ QString suffix;
+ QRegularExpressionMatch m = filter_re.match(filter);
+ if (m.hasMatch()) {
+ suffix = m.captured(1);
+ }
+ return suffix;
+}
+
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
@@ -529,13 +541,7 @@ QString getSaveFileName(QWidget *parent, const QString &caption, const QString &
/* Directly convert path to native OS path separators */
QString result = QDir::toNativeSeparators(QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter));
- /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
- QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
- QString selectedSuffix;
- if(filter_re.exactMatch(selectedFilter))
- {
- selectedSuffix = filter_re.cap(1);
- }
+ QString selectedSuffix = ExtractFirstSuffixFromFilter(selectedFilter);
/* Add suffix if needed */
QFileInfo info(result);
@@ -577,14 +583,8 @@ QString getOpenFileName(QWidget *parent, const QString &caption, const QString &
if(selectedSuffixOut)
{
- /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */
- QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]");
- QString selectedSuffix;
- if(filter_re.exactMatch(selectedFilter))
- {
- selectedSuffix = filter_re.cap(1);
- }
- *selectedSuffixOut = selectedSuffix;
+ *selectedSuffixOut = ExtractFirstSuffixFromFilter(selectedFilter);
+ ;
}
return result;
}
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 438d170cfc769..26dbda32f145b 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -191,6 +191,14 @@ namespace GUIUtil
*/
QString getDefaultDataDirectory();
+ /**
+ * Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...).
+ *
+ * @param[in] filter Filter specification such as "Comma Separated Files (*.csv)"
+ * @return QString
+ */
+ QString ExtractFirstSuffixFromFilter(const QString& filter);
+
/** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
when no suffix is provided by the user.
diff --git a/src/qt/initexecutor.cpp b/src/qt/initexecutor.cpp
index 87d9ecda5b987..4db90d041ebc2 100644
--- a/src/qt/initexecutor.cpp
+++ b/src/qt/initexecutor.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#include
#include
@@ -20,7 +21,7 @@
InitExecutor::InitExecutor(interfaces::Node& node)
: QObject(), m_node(node)
{
- this->moveToThread(&m_thread);
+ m_context.moveToThread(&m_thread);
m_thread.start();
}
@@ -40,46 +41,52 @@ void InitExecutor::handleRunawayException(const std::exception_ptr e)
void InitExecutor::initialize()
{
- try {
- util::ThreadRename("qt-init");
- qDebug() << __func__ << ": Running initialization in thread";
- interfaces::BlockAndHeaderTipInfo tip_info;
- bool rv = m_node.appInitMain(&tip_info);
- Q_EMIT initializeResult(rv, tip_info);
- } catch (...) {
- handleRunawayException(std::current_exception());
- }
+ GUIUtil::ObjectInvoke(&m_context, [this] {
+ try {
+ util::ThreadRename("qt-init");
+ qDebug() << "Running initialization in thread";
+ interfaces::BlockAndHeaderTipInfo tip_info;
+ bool rv = m_node.appInitMain(&tip_info);
+ Q_EMIT initializeResult(rv, tip_info);
+ } catch (...) {
+ handleRunawayException(std::current_exception());
+ }
+ });
}
void InitExecutor::restart(QStringList args)
{
- static bool executing_restart{false};
+ GUIUtil::ObjectInvoke(&m_context, [this, args] {
+ static bool executing_restart{false};
- if(!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
- executing_restart = true;
- try {
- qDebug() << __func__ << ": Running Restart in thread";
- m_node.appPrepareShutdown();
- qDebug() << __func__ << ": Shutdown finished";
- Q_EMIT shutdownResult();
- CExplicitNetCleanup::callCleanup();
- QProcess::startDetached(QApplication::applicationFilePath(), args);
- qDebug() << __func__ << ": Restart initiated...";
- QApplication::quit();
- } catch (...) {
- handleRunawayException(std::current_exception());
+ if (!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
+ executing_restart = true;
+ try {
+ qDebug() << "Running Restart in thread";
+ m_node.appPrepareShutdown();
+ qDebug() << "Shutdown finished";
+ Q_EMIT shutdownResult();
+ CExplicitNetCleanup::callCleanup();
+ QProcess::startDetached(QApplication::applicationFilePath(), args);
+ qDebug() << "Restart initiated...";
+ QApplication::quit();
+ } catch (...) {
+ handleRunawayException(std::current_exception());
+ }
}
- }
+ });
}
void InitExecutor::shutdown()
{
- try {
- qDebug() << __func__ << ": Running Shutdown in thread";
- m_node.appShutdown();
- qDebug() << __func__ << ": Shutdown finished";
- Q_EMIT shutdownResult();
- } catch (...) {
- handleRunawayException(std::current_exception());
- }
+ GUIUtil::ObjectInvoke(&m_context, [this] {
+ try {
+ qDebug() << "Running Shutdown in thread";
+ m_node.appShutdown();
+ qDebug() << "Shutdown finished";
+ Q_EMIT shutdownResult();
+ } catch (...) {
+ handleRunawayException(std::current_exception());
+ }
+ });
}
diff --git a/src/qt/initexecutor.h b/src/qt/initexecutor.h
index f4f11fca8b127..378b42a10434c 100644
--- a/src/qt/initexecutor.h
+++ b/src/qt/initexecutor.h
@@ -41,6 +41,7 @@ public Q_SLOTS:
void handleRunawayException(const std::exception_ptr e);
interfaces::Node& m_node;
+ QObject m_context;
QThread m_thread;
};
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index a7881f8a6c92b..6ede8902ca30c 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -9,16 +9,19 @@
#include
#include
+#include
+#include
#include
-OpenURIDialog::OpenURIDialog(QWidget *parent) :
- QDialog(parent, GUIUtil::dialog_flags),
- ui(new Ui::OpenURIDialog)
+OpenURIDialog::OpenURIDialog(QWidget* parent) : QDialog(parent, GUIUtil::dialog_flags),
+ ui(new Ui::OpenURIDialog)
{
ui->setupUi(this);
+ GUIUtil::setIcon(ui->pasteButton, "editpaste");
+ QObject::connect(ui->pasteButton, &QAbstractButton::clicked, ui->uriEdit, &QLineEdit::paste);
+
GUIUtil::updateFonts();
GUIUtil::disableMacFocusRect(this);
-
GUIUtil::handleCloseWindowShortcut(this);
}
@@ -35,11 +38,19 @@ QString OpenURIDialog::getURI()
void OpenURIDialog::accept()
{
SendCoinsRecipient rcp;
- if(GUIUtil::parseBitcoinURI(getURI(), &rcp))
- {
+ if (GUIUtil::parseBitcoinURI(getURI(), &rcp)) {
/* Only accept value URIs */
QDialog::accept();
} else {
ui->uriEdit->setValid(false);
}
}
+
+void OpenURIDialog::changeEvent(QEvent* e)
+{
+ QDialog::changeEvent(e);
+ if (e->type() == QEvent::StyleChange) {
+ // Adjust button icon colors on theme changes
+ GUIUtil::setIcon(ui->pasteButton, "editpaste");
+ }
+}
diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h
index efe4b86f3721d..14654c30e9d4d 100644
--- a/src/qt/openuridialog.h
+++ b/src/qt/openuridialog.h
@@ -16,16 +16,17 @@ class OpenURIDialog : public QDialog
Q_OBJECT
public:
- explicit OpenURIDialog(QWidget *parent);
+ explicit OpenURIDialog(QWidget* parent);
~OpenURIDialog();
QString getURI();
protected Q_SLOTS:
void accept() override;
+ void changeEvent(QEvent* e) override;
private:
- Ui::OpenURIDialog *ui;
+ Ui::OpenURIDialog* ui;
};
#endif // BITCOIN_QT_OPENURIDIALOG_H
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 7b4b517886a11..f818ced681cf1 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -262,9 +262,26 @@ void OptionsModel::Init(bool resetSettings)
if (!settings.contains("fListen"))
settings.setValue("fListen", DEFAULT_LISTEN);
- if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool())) {
+ const bool listen{settings.value("fListen").toBool()};
+ if (!gArgs.SoftSetBoolArg("-listen", listen)) {
addOverriddenOption("-listen");
- } else if (!settings.value("fListen").toBool()) {
+ } else if (!listen) {
+ // We successfully set -listen=0, thus mimic the logic from InitParameterInteraction():
+ // "parameter interaction: -listen=0 -> setting -listenonion=0".
+ //
+ // Both -listen and -listenonion default to true.
+ //
+ // The call order is:
+ //
+ // InitParameterInteraction()
+ // would set -listenonion=0 if it sees -listen=0, but for bitcoin-qt with
+ // fListen=false -listen is 1 at this point
+ //
+ // OptionsModel::Init()
+ // (this method) can flip -listen from 1 to 0 if fListen=false
+ //
+ // AppInitParameterInteraction()
+ // raises an error if -listen=0 and -listenonion=1
gArgs.SoftSetBoolArg("-listenonion", false);
}
diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp
index d19a88653c390..e66e8a5d328d5 100644
--- a/src/qt/qvalidatedlineedit.cpp
+++ b/src/qt/qvalidatedlineedit.cpp
@@ -14,6 +14,12 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}
+void QValidatedLineEdit::setText(const QString& text)
+{
+ QLineEdit::setText(text);
+ checkValidity();
+}
+
void QValidatedLineEdit::setValid(bool _valid)
{
if(_valid == this->valid)
@@ -27,7 +33,7 @@ void QValidatedLineEdit::setValid(bool _valid)
}
else
{
- setStyleSheet(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_INVALID));
+ setStyleSheet("QValidatedLineEdit { " + GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_INVALID) + " }");
}
this->valid = _valid;
}
@@ -105,6 +111,7 @@ void QValidatedLineEdit::checkValidity()
void QValidatedLineEdit::setCheckValidator(const QValidator *v)
{
checkValidator = v;
+ checkValidity();
}
bool QValidatedLineEdit::isValid()
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index b32305f5e193f..12d35aa2645c8 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -29,6 +29,7 @@ class QValidatedLineEdit : public QLineEdit
const QValidator *checkValidator;
public Q_SLOTS:
+ void setText(const QString&);
void setValid(bool valid);
void setEnabled(bool enabled);
diff --git a/src/qt/res/css/general.css b/src/qt/res/css/general.css
index af65262129052..b0eea68c0d61c 100644
--- a/src/qt/res/css/general.css
+++ b/src/qt/res/css/general.css
@@ -1259,6 +1259,13 @@ QDialog#OpenURIDialog {
QDialog#OpenURIDialog QLabel#label { /* URI Label */
}
+QDialog#OpenURIDialog .QToolButton { /* General Settings for Pay To Icons */
+ background-color: #00000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 0;
+}
+
/******************************************************
OptionsDialog
******************************************************/
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 3e0be6da11a69..fe623b8435eeb 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -8,6 +8,7 @@
#include
#include
+#include
#include
#include
#include
@@ -22,8 +23,9 @@
#include
#include
-#include
#include
+#include
+#include
namespace
{
@@ -114,14 +116,19 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
+ AddressBookPage address_book{AddressBookPage::ForEditing, AddressBookPage::SendingTab};
+ address_book.setModel(walletModel.getAddressTableModel());
+ auto table_view = address_book.findChild("tableView");
+ QCOMPARE(table_view->model()->rowCount(), 1);
+
EditAddressAndSubmit(
&editAddressDialog, QString("uhoh"), preexisting_r_address,
QString(
"Address \"%1\" already exists as a receiving address with label "
"\"%2\" and so cannot be added as a sending address."
).arg(preexisting_r_address).arg(r_label));
-
check_addbook_size(2);
+ QCOMPARE(table_view->model()->rowCount(), 1);
EditAddressAndSubmit(
&editAddressDialog, QString("uhoh, different"), preexisting_s_address,
@@ -129,15 +136,15 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
"The entered address \"%1\" is already in the address book with "
"label \"%2\"."
).arg(preexisting_s_address).arg(s_label));
-
check_addbook_size(2);
+ QCOMPARE(table_view->model()->rowCount(), 1);
// Submit a new address which should add successfully - we expect the
// warning message to be blank.
EditAddressAndSubmit(
&editAddressDialog, QString("new"), new_address, QString(""));
-
check_addbook_size(3);
+ QCOMPARE(table_view->model()->rowCount(), 2);
}
} // namespace
diff --git a/src/qt/test/optiontests.cpp b/src/qt/test/optiontests.cpp
new file mode 100644
index 0000000000000..343755103cf2d
--- /dev/null
+++ b/src/qt/test/optiontests.cpp
@@ -0,0 +1,78 @@
+// 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
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+//! Entry point for BitcoinApplication tests.
+void OptionTests::optionTests()
+{
+ // Test regression https://github.com/bitcoin/bitcoin/issues/24457. Ensure
+ // that setting integer prune value doesn't cause an exception to be thrown
+ // in the OptionsModel constructor
+ gArgs.LockSettings([&](util::Settings& settings) {
+ settings.forced_settings.erase("prune");
+ settings.rw_settings["prune"] = 3814;
+ });
+ gArgs.WriteSettingsFile();
+ OptionsModel{};
+ gArgs.LockSettings([&](util::Settings& settings) {
+ settings.rw_settings.erase("prune");
+ });
+ gArgs.WriteSettingsFile();
+}
+
+void OptionTests::parametersInteraction()
+{
+ // Test that the bug https://github.com/bitcoin-core/gui/issues/567 does not resurface.
+ // It was fixed via https://github.com/bitcoin-core/gui/pull/568.
+ // With fListen=false in ~/.config/Bitcoin/Bitcoin-Qt.conf and all else left as default,
+ // bitcoin-qt should set both -listen and -listenonion to false and start successfully.
+ gArgs.ClearPathCache();
+
+ gArgs.LockSettings([&](util::Settings& s) {
+ s.forced_settings.erase("listen");
+ s.forced_settings.erase("listenonion");
+ });
+ QVERIFY(!gArgs.IsArgSet("-listen"));
+ QVERIFY(!gArgs.IsArgSet("-listenonion"));
+
+ QSettings settings;
+ settings.setValue("fListen", false);
+
+ OptionsModel{};
+
+ const bool expected{false};
+
+ QVERIFY(gArgs.IsArgSet("-listen"));
+ QCOMPARE(gArgs.GetBoolArg("-listen", !expected), expected);
+
+ QVERIFY(gArgs.IsArgSet("-listenonion"));
+ QCOMPARE(gArgs.GetBoolArg("-listenonion", !expected), expected);
+
+ QVERIFY(AppInitParameterInteraction(gArgs));
+
+ // cleanup
+ settings.remove("fListen");
+ QVERIFY(!settings.contains("fListen"));
+ gArgs.ClearPathCache();
+}
+
+void OptionTests::extractFilter()
+{
+ QString filter = QString("Partially Signed Transaction (Binary) (*.psbt)");
+ QCOMPARE(GUIUtil::ExtractFirstSuffixFromFilter(filter), "psbt");
+
+ filter = QString("Image (*.png *.jpg)");
+ QCOMPARE(GUIUtil::ExtractFirstSuffixFromFilter(filter), "png");
+}
diff --git a/src/qt/test/optiontests.h b/src/qt/test/optiontests.h
new file mode 100644
index 0000000000000..d5a3bfd6b4a07
--- /dev/null
+++ b/src/qt/test/optiontests.h
@@ -0,0 +1,27 @@
+// Copyright (c) 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_OPTIONTESTS_H
+#define BITCOIN_QT_TEST_OPTIONTESTS_H
+
+#include
+
+#include
+
+class OptionTests : public QObject
+{
+ Q_OBJECT
+public:
+ explicit OptionTests(interfaces::Node& node) : m_node(node) {}
+
+private Q_SLOTS:
+ void optionTests();
+ void parametersInteraction();
+ void extractFilter();
+
+private:
+ interfaces::Node& m_node;
+};
+
+#endif // BITCOIN_QT_TEST_OPTIONTESTS_H
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 465bc62060fa8..af73890799421 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -9,8 +9,8 @@
#include
#include
-#include
#include
+#include
#include
#include
#include
@@ -22,8 +22,10 @@
#endif // ENABLE_WALLET
#include
+#include
#include
#include
+
#include
#if defined(QT_STATIC)
@@ -37,6 +39,8 @@ Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
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
@@ -67,8 +71,6 @@ int main(int argc, char* argv[])
gArgs.ForceSetArg("-upnp", "0");
gArgs.ForceSetArg("-natpmp", "0");
- bool fInvalid = false;
-
// 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.
@@ -83,31 +85,35 @@ int main(int argc, char* argv[])
app.setApplicationName("Dash-Qt-test");
app.node().context()->args = &gArgs; // Make gArgs available in the NodeContext
+
+ int num_test_failures{0};
+
AppTests app_tests(app);
- if (QTest::qExec(&app_tests) != 0) {
- fInvalid = true;
- }
+ num_test_failures += QTest::qExec(&app_tests);
+
+ OptionTests options_tests(app.node());
+ num_test_failures += QTest::qExec(&options_tests);
+
URITests test1;
- if (QTest::qExec(&test1) != 0) {
- fInvalid = true;
- }
+ num_test_failures += QTest::qExec(&test1);
+
RPCNestedTests test3(app.node());
- if (QTest::qExec(&test3) != 0) {
- fInvalid = true;
- }
+ num_test_failures += QTest::qExec(&test3);
+
#ifdef ENABLE_WALLET
WalletTests test5(app.node());
- if (QTest::qExec(&test5) != 0) {
- fInvalid = true;
- }
+ num_test_failures += QTest::qExec(&test5);
+
AddressBookTests test6(app.node());
- if (QTest::qExec(&test6) != 0) {
- fInvalid = true;
- }
+ num_test_failures += QTest::qExec(&test6);
#endif
-
TrafficGraphDataTests test7;
- if (QTest::qExec(&test7) != 0)
- fInvalid = true;
- return fInvalid;
+ num_test_failures += QTest::qExec(&test7);
+
+ if (num_test_failures) {
+ qWarning("\nFailed tests: %d\n", num_test_failures);
+ } else {
+ qDebug("\nAll tests passed.\n");
+ }
+ return num_test_failures;
}
diff --git a/src/qt/transactionoverviewwidget.cpp b/src/qt/transactionoverviewwidget.cpp
new file mode 100644
index 0000000000000..360a1364fb423
--- /dev/null
+++ b/src/qt/transactionoverviewwidget.cpp
@@ -0,0 +1,27 @@
+// Copyright (c) 2021 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
+#include
+#include
+
+TransactionOverviewWidget::TransactionOverviewWidget(QWidget* parent)
+ : QListView(parent) {}
+
+QSize TransactionOverviewWidget::sizeHint() const
+{
+ return {sizeHintForColumn(TransactionTableModel::ToAddress), QListView::sizeHint().height()};
+}
+
+void TransactionOverviewWidget::showEvent(QShowEvent* event)
+{
+ Q_UNUSED(event);
+ QSizePolicy sp = sizePolicy();
+ sp.setHorizontalPolicy(QSizePolicy::Minimum);
+ setSizePolicy(sp);
+}
diff --git a/src/qt/transactionoverviewwidget.h b/src/qt/transactionoverviewwidget.h
index 2bdead7bc40e9..0572e84090f6e 100644
--- a/src/qt/transactionoverviewwidget.h
+++ b/src/qt/transactionoverviewwidget.h
@@ -5,11 +5,8 @@
#ifndef BITCOIN_QT_TRANSACTIONOVERVIEWWIDGET_H
#define BITCOIN_QT_TRANSACTIONOVERVIEWWIDGET_H
-#include
-
#include
#include
-#include
QT_BEGIN_NAMESPACE
class QShowEvent;
@@ -21,21 +18,11 @@ class TransactionOverviewWidget : public QListView
Q_OBJECT
public:
- explicit TransactionOverviewWidget(QWidget* parent = nullptr) : QListView(parent) {}
-
- QSize sizeHint() const override
- {
- return {sizeHintForColumn(TransactionTableModel::ToAddress), QListView::sizeHint().height()};
- }
+ explicit TransactionOverviewWidget(QWidget* parent = nullptr);
+ QSize sizeHint() const override;
protected:
- void showEvent(QShowEvent* event) override
- {
- Q_UNUSED(event);
- QSizePolicy sp = sizePolicy();
- sp.setHorizontalPolicy(QSizePolicy::Minimum);
- setSizePolicy(sp);
- }
+ void showEvent(QShowEvent* event) override;
};
#endif // BITCOIN_QT_TRANSACTIONOVERVIEWWIDGET_H
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 83743878b3d2b..d21ae4312bb55 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -23,7 +23,8 @@
#include
#include
#include
-#include
+#include
+#include
#include
#include
#include
@@ -48,9 +49,8 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, HelpMode helpMode) :
QString licenseInfoHTML = QString::fromStdString(licenseInfo);
// Make URLs clickable
- QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2);
- uri.setMinimal(true); // use non-greedy matching
- licenseInfoHTML.replace(uri, QString("\\1").arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)));
+ QRegularExpression uri(QStringLiteral("<(.*)>"), QRegularExpression::InvertedGreedinessOption);
+ licenseInfoHTML.replace(uri, QString("\\1").arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)));
// Replace newlines with HTML breaks
licenseInfoHTML.replace("\n", "
");
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index f3781d1621c00..b52152b4c2202 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -78,14 +78,13 @@ void WalletFrame::setClientModel(ClientModel *_clientModel)
}
}
-bool WalletFrame::addWallet(WalletModel* walletModel, WalletView* walletView)
+bool WalletFrame::addView(WalletView* walletView)
{
- if (!clientModel || !walletModel) return false;
+ if (!clientModel) return false;
- if (mapWalletViews.count(walletModel) > 0) return false;
+ if (mapWalletViews.count(walletView->getWalletModel()) > 0) return false;
walletView->setClientModel(clientModel);
- walletView->setWalletModel(walletModel);
walletView->showOutOfSyncWarning(bOutOfSync);
WalletView* current_wallet_view = currentWalletView();
@@ -96,7 +95,7 @@ bool WalletFrame::addWallet(WalletModel* walletModel, WalletView* walletView)
}
walletStack->addWidget(walletView);
- mapWalletViews[walletModel] = walletView;
+ mapWalletViews[walletView->getWalletModel()] = walletView;
return true;
}
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 948af49ad6d82..7be1e3d467e8a 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -37,7 +37,7 @@ class WalletFrame : public QFrame
void setClientModel(ClientModel *clientModel);
- bool addWallet(WalletModel* walletModel, WalletView* walletView);
+ bool addView(WalletView* walletView);
void setCurrentWallet(WalletModel* wallet_model);
void removeWallet(WalletModel* wallet_model);
void removeAllWallets();
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index d4a88de83b97a..e89f4e363d9b0 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -356,6 +356,11 @@ WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
if(!m_wallet->isCrypted())
{
+ // A previous bug allowed for watchonly wallets to be encrypted (encryption keys set, but nothing is actually encrypted).
+ // To avoid misrepresenting the encryption status of such wallets, we only return NoKeys for watchonly wallets that are unencrypted.
+ if (m_wallet->privateKeysDisabled()) {
+ return NoKeys;
+ }
return Unencrypted;
}
else if(m_wallet->isLocked(true))
@@ -436,7 +441,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel,
QString strPurpose = QString::fromStdString(purpose);
qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
- bool invoked = QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
+ bool invoked = QMetaObject::invokeMethod(walletmodel, "updateAddressBook",
Q_ARG(QString, strAddress),
Q_ARG(QString, strLabel),
Q_ARG(bool, isMine),
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index d15f65af91595..ce86fbfcf61e4 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -70,6 +70,7 @@ class WalletModel : public QObject
enum EncryptionStatus
{
+ NoKeys, // wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)
Unencrypted, // !wallet->IsCrypted()
Locked, // wallet->IsCrypted() && wallet->IsLocked(true)
UnlockedForMixingOnly, // wallet->IsCrypted() && !wallet->IsLocked(true) && wallet->IsLocked()
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 390df73576c18..899f0bc39c5af 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -35,18 +35,23 @@
#include
#include
-WalletView::WalletView(QWidget* parent) :
- QStackedWidget(parent),
- clientModel(nullptr),
- walletModel(nullptr)
+WalletView::WalletView(WalletModel* wallet_model, QWidget* parent)
+ : QStackedWidget(parent),
+ clientModel(nullptr),
+ walletModel(wallet_model)
{
+ assert(walletModel);
+
// Create tabs
overviewPage = new OverviewPage();
+ overviewPage->setWalletModel(walletModel);
transactionsPage = new QWidget(this);
QVBoxLayout *vbox = new QVBoxLayout();
QHBoxLayout *hbox_buttons = new QHBoxLayout();
transactionView = new TransactionView(this);
+ transactionView->setModel(walletModel);
+
vbox->addWidget(transactionView);
QPushButton *exportButton = new QPushButton(tr("&Export"), this);
exportButton->setToolTip(tr("Export the data in the current tab to a file"));
@@ -75,11 +80,19 @@ WalletView::WalletView(QWidget* parent) :
transactionsPage->setLayout(vbox);
receiveCoinsPage = new ReceiveCoinsDialog();
+ receiveCoinsPage->setModel(walletModel);
+
sendCoinsPage = new SendCoinsDialog();
+ sendCoinsPage->setModel(walletModel);
+
coinJoinCoinsPage = new SendCoinsDialog(true);
+ coinJoinCoinsPage->setModel(walletModel);
usedSendingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
+ usedSendingAddressesPage->setModel(walletModel->getAddressTableModel());
+
usedReceivingAddressesPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
+ usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel());
addWidget(overviewPage);
addWidget(transactionsPage);
@@ -90,6 +103,7 @@ WalletView::WalletView(QWidget* parent) :
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
masternodeListPage = new MasternodeList();
+ masternodeListPage->setWalletModel(walletModel);
addWidget(masternodeListPage);
}
if (settings.value("fShowGovernanceTab").toBool()) {
@@ -123,6 +137,21 @@ WalletView::WalletView(QWidget* parent) :
connect(this, &WalletView::setPrivacy, overviewPage, &OverviewPage::setPrivacy);
+ // Receive and pass through messages from wallet model
+ connect(walletModel, &WalletModel::message, this, &WalletView::message);
+
+ // Handle changes in encryption status
+ connect(walletModel, &WalletModel::encryptionStatusChanged, this, &WalletView::encryptionStatusChanged);
+
+ // Balloon pop-up for new transaction
+ connect(walletModel->getTransactionTableModel(), &TransactionTableModel::rowsInserted, this, &WalletView::processNewTransaction);
+
+ // Ask for passphrase if needed
+ connect(walletModel, &WalletModel::requireUnlock, this, &WalletView::unlockWallet);
+
+ // Show progress dialog
+ connect(walletModel, &WalletModel::showProgress, this, &WalletView::showProgress);
+
GUIUtil::disableMacFocusRect(this);
}
@@ -150,50 +179,15 @@ void WalletView::setClientModel(ClientModel *_clientModel)
if (settings.value("fShowGovernanceTab").toBool() && governanceListPage != nullptr) {
governanceListPage->setClientModel(_clientModel);
}
- if (walletModel) walletModel->setClientModel(_clientModel);
-}
-
-void WalletView::setWalletModel(WalletModel *_walletModel)
-{
- this->walletModel = _walletModel;
-
- // Put transaction list in tabs
- transactionView->setModel(_walletModel);
- overviewPage->setWalletModel(_walletModel);
- QSettings settings;
- if (settings.value("fShowMasternodesTab").toBool()) {
- masternodeListPage->setWalletModel(_walletModel);
- }
- receiveCoinsPage->setModel(_walletModel);
- sendCoinsPage->setModel(_walletModel);
- coinJoinCoinsPage->setModel(_walletModel);
- usedReceivingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);
- usedSendingAddressesPage->setModel(_walletModel ? _walletModel->getAddressTableModel() : nullptr);
-
- if (_walletModel)
- {
- // Receive and pass through messages from wallet model
- connect(_walletModel, &WalletModel::message, this, &WalletView::message);
-
- // Handle changes in encryption status
- connect(_walletModel, &WalletModel::encryptionStatusChanged, this, &WalletView::encryptionStatusChanged);
-
- // Balloon pop-up for new transaction
- connect(_walletModel->getTransactionTableModel(), &TransactionTableModel::rowsInserted, this, &WalletView::processNewTransaction);
-
- // Ask for passphrase if needed
- connect(_walletModel, &WalletModel::requireUnlock, this, &WalletView::unlockWallet);
-
- // Show progress dialog
- connect(_walletModel, &WalletModel::showProgress, this, &WalletView::showProgress);
- }
+ walletModel->setClientModel(_clientModel);
}
void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
// Prevent balloon-spam when initial block download is in progress
- if (!walletModel || !clientModel || clientModel->node().isInitialBlockDownload())
+ if (!clientModel || clientModel->node().isInitialBlockDownload()) {
return;
+ }
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
if (!ttm || ttm->processingQueuedTransactions())
@@ -302,8 +296,6 @@ void WalletView::showOutOfSyncWarning(bool fShow)
void WalletView::encryptWallet()
{
- if(!walletModel)
- return;
AskPassphraseDialog dlg(AskPassphraseDialog::Encrypt, this);
dlg.setModel(walletModel);
dlg.exec();
@@ -340,10 +332,7 @@ void WalletView::changePassphrase()
void WalletView::unlockWallet(bool fForMixingOnly)
{
- if(!walletModel)
- return;
// Unlock wallet when requested by wallet model
-
if (walletModel->getEncryptionStatus() == WalletModel::Locked || walletModel->getEncryptionStatus() == WalletModel::UnlockedForMixingOnly)
{
AskPassphraseDialog dlg(fForMixingOnly ? AskPassphraseDialog::UnlockMixing : AskPassphraseDialog::Unlock, this);
@@ -354,25 +343,16 @@ void WalletView::unlockWallet(bool fForMixingOnly)
void WalletView::lockWallet()
{
- if(!walletModel)
- return;
-
walletModel->setWalletLocked(true);
}
void WalletView::usedSendingAddresses()
{
- if(!walletModel)
- return;
-
GUIUtil::bringToFront(usedSendingAddressesPage);
}
void WalletView::usedReceivingAddresses()
{
- if(!walletModel)
- return;
-
GUIUtil::bringToFront(usedReceivingAddressesPage);
}
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index fa281690a7472..6c0f232b57595 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -37,19 +37,14 @@ class WalletView : public QStackedWidget
Q_OBJECT
public:
- explicit WalletView(QWidget* parent);
+ explicit WalletView(WalletModel* wallet_model, QWidget* parent);
~WalletView();
/** Set the client model.
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
*/
void setClientModel(ClientModel *clientModel);
- WalletModel *getWalletModel() { return walletModel; }
- /** Set the wallet model.
- The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
- functionality.
- */
- void setWalletModel(WalletModel *walletModel);
+ WalletModel* getWalletModel() const noexcept { return walletModel; }
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
@@ -57,7 +52,12 @@ class WalletView : public QStackedWidget
private:
ClientModel *clientModel;
- WalletModel *walletModel;
+
+ //!
+ //! The wallet model represents a bitcoin wallet, and offers access to
+ //! the list of transactions, address book and sending functionality.
+ //!
+ WalletModel* const walletModel;
OverviewPage *overviewPage;
QWidget *transactionsPage;
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index d4b30767dab9b..80d6625e67003 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -280,20 +280,14 @@ FUZZ_TARGET(string)
}
{
- const int atoi_result = atoi(random_string_1.c_str());
const int locale_independent_atoi_result = LocaleIndependentAtoi(random_string_1);
const int64_t atoi64_result = atoi64_legacy(random_string_1);
- const bool out_of_range = atoi64_result < std::numeric_limits::min() || atoi64_result > std::numeric_limits::max();
- if (out_of_range) {
- assert(locale_independent_atoi_result == 0);
- } else {
- assert(atoi_result == locale_independent_atoi_result);
- }
+ assert(locale_independent_atoi_result == std::clamp(atoi64_result, std::numeric_limits::min(), std::numeric_limits::max()));
}
{
const int64_t atoi64_result = atoi64_legacy(random_string_1);
const int64_t locale_independent_atoi_result = LocaleIndependentAtoi(random_string_1);
- assert(atoi64_result == locale_independent_atoi_result || locale_independent_atoi_result == 0);
+ assert(atoi64_result == locale_independent_atoi_result);
}
}
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index a2c3e1876a81b..5a6d17eec14a3 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -3,27 +3,21 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
+#include
+#include
#include
#include
+#include
#include
#include
#include
#include
-namespace getarg_tests{
- class LocalTestingSetup : BasicTestingSetup {
- protected:
- void SetupArgs(const std::vector>& args);
- void ResetArgs(const std::string& strArg);
- ArgsManager m_local_args;
- };
-}
-
-BOOST_FIXTURE_TEST_SUITE(getarg_tests, LocalTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup)
-void LocalTestingSetup :: ResetArgs(const std::string& strArg)
+void ResetArgs(ArgsManager& local_args, const std::string& strArg)
{
std::vector vecArg;
if (strArg.size()) {
@@ -39,210 +33,330 @@ void LocalTestingSetup :: ResetArgs(const std::string& strArg)
vecChar.push_back(s.c_str());
std::string error;
- BOOST_CHECK(m_local_args.ParseParameters(vecChar.size(), vecChar.data(), error));
+ BOOST_CHECK(local_args.ParseParameters(vecChar.size(), vecChar.data(), error));
}
-void LocalTestingSetup :: SetupArgs(const std::vector>& args)
+void SetupArgs(ArgsManager& local_args, const std::vector>& args)
{
- m_local_args.ClearArgs();
for (const auto& arg : args) {
- m_local_args.AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
+ local_args.AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
}
}
+// Test behavior of GetArg functions when string, integer, and boolean types
+// are specified in the settings.json file. GetArg functions are convenience
+// functions. The GetSetting method can always be used instead of GetArg
+// methods to retrieve original values, and there's not always an objective
+// answer to what GetArg behavior is best in every case. This test makes sure
+// there's test coverage for whatever the current behavior is, so it's not
+// broken or changed unintentionally.
+BOOST_AUTO_TEST_CASE(setting_args)
+{
+ ArgsManager args;
+ SetupArgs(args, {{"-foo", ArgsManager::ALLOW_ANY}});
+
+ auto set_foo = [&](const util::SettingsValue& value) {
+ args.LockSettings([&](util::Settings& settings) {
+ settings.rw_settings["foo"] = value;
+ });
+ };
+
+ set_foo("str");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"str\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "str");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo("99");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"99\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 99);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo("3.25");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"3.25\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 3);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo("0");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"0\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo("");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo(99);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "99");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 99);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(3.25);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "3.25");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25");
+ BOOST_CHECK_THROW(args.GetArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(0);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "0");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 0);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(true);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "true");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "1");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 1);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo(false);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "false");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo(UniValue::VOBJ);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "{}");
+ BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(UniValue::VARR);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "[]");
+ BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(UniValue::VNULL);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "null");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "default");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", 100), 100);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+}
+
BOOST_AUTO_TEST_CASE(boolarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
- SetupArgs({foo});
- ResetArgs("-foo");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ SetupArgs(local_args, {foo});
+ ResetArgs(local_args, "-foo");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-fo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-fo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-fo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-fo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-fooo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-fooo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-fooo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-fooo", true));
- ResetArgs("-foo=0");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=0");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=1");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=1");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
// New 0.6 feature: auto-map -nosomething to !-something:
- ResetArgs("-nofoo");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-nofoo");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo -nofoo"); // -nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo -nofoo"); // -nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=1 -nofoo=1"); // -nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=1 -nofoo=1"); // -nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=0 -nofoo=0"); // -nofoo=0 should win
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=0 -nofoo=0"); // -nofoo=0 should win
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
// New 0.6 feature: treat -- same as -:
- ResetArgs("--foo=1");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
-
- ResetArgs("--nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "--foo=1");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "--nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
}
BOOST_AUTO_TEST_CASE(stringarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "eleven");
-
- ResetArgs("-foo -bar");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "");
-
- ResetArgs("-foo=");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "");
-
- ResetArgs("-foo=11");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "11");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "11");
-
- ResetArgs("-foo=eleven");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "eleven");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "eleven");
-
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven");
+
+ ResetArgs(local_args, "-foo -bar");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "");
+
+ ResetArgs(local_args, "-foo=");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "");
+
+ ResetArgs(local_args, "-foo=11");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "11");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "11");
+
+ ResetArgs(local_args, "-foo=eleven");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "eleven");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven");
}
BOOST_AUTO_TEST_CASE(intarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", 11), 11);
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", 0), 0);
-
- ResetArgs("-foo -bar");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", 11), 0);
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-bar", 11), 0);
-
- ResetArgs("-foo=11 -bar=12");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", 0), 11);
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-bar", 11), 12);
-
- ResetArgs("-foo=NaN -bar=NotANumber");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", 1), 0);
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-bar", 11), 0);
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 11), 11);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 0), 0);
+
+ ResetArgs(local_args, "-foo -bar");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 11), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", 11), 0);
+
+ // Check under-/overflow behavior.
+ ResetArgs(local_args, "-foo=-9223372036854775809 -bar=9223372036854775808");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 0), std::numeric_limits::min());
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", 0), std::numeric_limits::max());
+
+ ResetArgs(local_args, "-foo=11 -bar=12");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 0), 11);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", 11), 12);
+
+ ResetArgs(local_args, "-foo=NaN -bar=NotANumber");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", 1), 0);
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", 11), 0);
}
BOOST_AUTO_TEST_CASE(patharg)
{
+ ArgsManager local_args;
+
const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY);
- SetupArgs({dir});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{});
+ SetupArgs(local_args, {dir});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), fs::path{});
const fs::path root_path{"/"};
- ResetArgs("-dir=/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
#ifdef WIN32
const fs::path win_root_path{"C:\\"};
- ResetArgs("-dir=C:\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.\\\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.\\\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
#endif
const fs::path absolute_path{"/home/user/.bitcoin"};
- ResetArgs("-dir=/home/user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/root/../home/user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/root/../home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/./user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/./user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
const fs::path relative_path{"user/.bitcoin"};
- ResetArgs("-dir=user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=somewhere/../user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=somewhere/../user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/./.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/./.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/.bitcoin/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/.bitcoin//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/.bitcoin/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/.bitcoin/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
- ResetArgs("-dir=user/.bitcoin/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
// Check negated and default argument handling. Specifying an empty argument
// is the same as not specifying the argument. This is convenient for
@@ -251,65 +365,71 @@ BOOST_AUTO_TEST_CASE(patharg)
// distinguished from -dir case with no assignment, but #16545 would add the
// ability to distinguish these in the future (and treat the no-assign case
// like an imperative command or an error).
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
- ResetArgs("-dir=override");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"override"});
- ResetArgs("-dir=");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
- ResetArgs("-dir");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
- ResetArgs("-nodir");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{""});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-dir=override");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"override"});
+ ResetArgs(local_args, "-dir=");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-dir");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-nodir");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{""});
}
BOOST_AUTO_TEST_CASE(doubledash)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("--foo");
- BOOST_CHECK_EQUAL(m_local_args.GetBoolArg("-foo", false), true);
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "--foo");
+ BOOST_CHECK_EQUAL(local_args.GetBoolArg("-foo", false), true);
- ResetArgs("--foo=verbose --bar=1");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "verbose");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-bar", 0), 1);
+ ResetArgs(local_args, "--foo=verbose --bar=1");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "verbose");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-bar", 0), 1);
}
BOOST_AUTO_TEST_CASE(boolargno)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("-nofoo");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo=0");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-foo --nofoo"); // --nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo -foo"); // foo always wins:
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "-nofoo");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo=0");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-foo --nofoo"); // --nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo -foo"); // foo always wins:
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
}
BOOST_AUTO_TEST_CASE(logargs)
{
+ ArgsManager local_args;
+
const auto okaylog_bool = std::make_pair("-okaylog-bool", ArgsManager::ALLOW_BOOL);
const auto okaylog_negbool = std::make_pair("-okaylog-negbool", ArgsManager::ALLOW_BOOL);
const auto okaylog = std::make_pair("-okaylog", ArgsManager::ALLOW_ANY);
const auto dontlog = std::make_pair("-dontlog", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE);
- SetupArgs({okaylog_bool, okaylog_negbool, okaylog, dontlog});
- ResetArgs("-okaylog-bool -nookaylog-negbool -okaylog=public -dontlog=private");
+ SetupArgs(local_args, {okaylog_bool, okaylog_negbool, okaylog, dontlog});
+ ResetArgs(local_args, "-okaylog-bool -nookaylog-negbool -okaylog=public -dontlog=private");
// Everything logged to debug.log will also append to str
std::string str;
@@ -319,7 +439,7 @@ BOOST_AUTO_TEST_CASE(logargs)
});
// Log the arguments
- m_local_args.LogArgs();
+ local_args.LogArgs();
LogInstance().DeleteCallback(print_connection);
// Check that what should appear does, and what shouldn't doesn't.
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 699cd04fbe078..107361b50ded6 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -29,6 +29,8 @@
#include
#include
#include
+#include
+#include