diff --git a/src/Makefile.test.include b/src/Makefile.test.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -142,11 +142,14 @@ wallet/test/wallet_tests.cpp \ wallet/test/walletdb_tests.cpp \ wallet/test/wallet_crypto_tests.cpp \ - wallet/test/coinselector_tests.cpp + wallet/test/coinselector_tests.cpp \ + wallet/test/init_tests.cpp BITCOIN_TEST_SUITE += \ wallet/test/wallet_test_fixture.cpp \ - wallet/test/wallet_test_fixture.h + wallet/test/wallet_test_fixture.h \ + wallet/test/init_test_fixture.cpp \ + wallet/test/init_test_fixture.h endif test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -45,12 +45,14 @@ if(BUILD_BITCOIN_WALLET) set(BITCOIN_WALLET_TEST_FIXTURE + ../wallet/test/init_test_fixture.cpp ../wallet/test/wallet_test_fixture.cpp ) set(BITCOIN_WALLET_TESTS ../wallet/test/accounting_tests.cpp ../wallet/test/db_tests.cpp ../wallet/test/coinselector_tests.cpp + ../wallet/test/init_tests.cpp ../wallet/test/psbt_wallet_tests.cpp ../wallet/test/wallet_tests.cpp ../wallet/test/walletdb_tests.cpp diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -283,7 +283,11 @@ if (gArgs.IsArgSet("-walletdir")) { fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); - if (!fs::exists(wallet_dir)) { + boost::system::error_code error; + // The canonical path cleans the path, preventing >1 Berkeley + // environment instances for the same directory + fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); + if (error || !fs::exists(wallet_dir)) { return InitError( strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); @@ -291,11 +295,14 @@ return InitError( strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); + // The canonical path transforms relative paths into absolute ones, + // so we check the non-canonical version } else if (!wallet_dir.is_absolute()) { return InitError( strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); } + gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); } LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h new file mode 100644 --- /dev/null +++ b/src/wallet/test/init_test_fixture.h @@ -0,0 +1,21 @@ +// 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. + +#ifndef BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H +#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H + +#include + +struct InitWalletDirTestingSetup : public BasicTestingSetup { + explicit InitWalletDirTestingSetup( + const std::string &chainName = CBaseChainParams::MAIN); + ~InitWalletDirTestingSetup(); + void SetWalletDir(const fs::path &walletdir_path); + + fs::path m_datadir; + fs::path m_cwd; + std::map m_walletdir_path_cases; +}; + +#endif // BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp new file mode 100644 --- /dev/null +++ b/src/wallet/test/init_test_fixture.cpp @@ -0,0 +1,42 @@ +// 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 + +InitWalletDirTestingSetup::InitWalletDirTestingSetup( + const std::string &chainName) + : BasicTestingSetup(chainName) { + std::string sep; + sep += fs::path::preferred_separator; + + m_datadir = SetDataDir("tempdir"); + m_cwd = fs::current_path(); + + m_walletdir_path_cases["default"] = m_datadir / "wallets"; + m_walletdir_path_cases["custom"] = m_datadir / "my_wallets"; + m_walletdir_path_cases["nonexistent"] = m_datadir / "path_does_not_exist"; + m_walletdir_path_cases["file"] = m_datadir / "not_a_directory.dat"; + m_walletdir_path_cases["trailing"] = m_datadir / "wallets" / sep; + m_walletdir_path_cases["trailing2"] = m_datadir / "wallets" / sep / sep; + + fs::current_path(m_datadir); + m_walletdir_path_cases["relative"] = "wallets"; + + fs::create_directories(m_walletdir_path_cases["default"]); + fs::create_directories(m_walletdir_path_cases["custom"]); + fs::create_directories(m_walletdir_path_cases["relative"]); + std::ofstream f(m_walletdir_path_cases["file"].BOOST_FILESYSTEM_C_STR); + f.close(); +} + +InitWalletDirTestingSetup::~InitWalletDirTestingSetup() { + fs::current_path(m_cwd); +} + +void InitWalletDirTestingSetup::SetWalletDir(const fs::path &walletdir_path) { + gArgs.ForceSetArg("-walletdir", walletdir_path.string()); +} diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp new file mode 100644 --- /dev/null +++ b/src/wallet/test/init_tests.cpp @@ -0,0 +1,71 @@ +// 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 + +BOOST_FIXTURE_TEST_SUITE(init_tests, InitWalletDirTestingSetup) + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default) { + SetWalletDir(m_walletdir_path_cases["default"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == true); + fs::path walletdir = gArgs.GetArg("-walletdir", ""); + fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); + BOOST_CHECK(walletdir == expected_path); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom) { + SetWalletDir(m_walletdir_path_cases["custom"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == true); + fs::path walletdir = gArgs.GetArg("-walletdir", ""); + fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]); + BOOST_CHECK(walletdir == expected_path); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_does_not_exist) { + SetWalletDir(m_walletdir_path_cases["nonexistent"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == false); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_directory) { + SetWalletDir(m_walletdir_path_cases["file"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == false); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_relative) { + SetWalletDir(m_walletdir_path_cases["relative"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == false); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing) { + SetWalletDir(m_walletdir_path_cases["trailing"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == true); + fs::path walletdir = gArgs.GetArg("-walletdir", ""); + fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); + BOOST_CHECK(walletdir == expected_path); +} + +BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2) { + SetWalletDir(m_walletdir_path_cases["trailing2"]); + bool result = g_wallet_init_interface.Verify(Params()); + BOOST_CHECK(result == true); + fs::path walletdir = gArgs.GetArg("-walletdir", ""); + fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); + BOOST_CHECK(walletdir == expected_path); +} + +BOOST_AUTO_TEST_SUITE_END()