diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 9f394e720..b2e980bca 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -4,6 +4,7 @@ #include "deprecation.h" +#include "alert.h" #include "clientversion.h" #include "init.h" #include "ui_interface.h" @@ -12,7 +13,7 @@ static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); -void EnforceNodeDeprecation(int nHeight, bool forceLogging) { +void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { // Do not enforce deprecation in regtest or on testnet std::string networkID = Params().NetworkIDString(); @@ -36,6 +37,7 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging) { "-disabledeprecation=", CLIENT_VERSION_STR); } LogPrintf("*** %s\n", msg); + CAlert::Notify(msg, fThread); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); } if (!disableDeprecation) { @@ -56,6 +58,7 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging) { "-disabledeprecation=", CLIENT_VERSION_STR); } LogPrintf("*** %s\n", msg); + CAlert::Notify(msg, fThread); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_WARNING); } -} \ No newline at end of file +} diff --git a/src/deprecation.h b/src/deprecation.h index 3e361cab7..bd68b42ce 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -18,8 +18,11 @@ static const int DEPRECATION_WARN_LIMIT = 14 * 24 * 24; // 2 weeks /** * Checks whether the node is deprecated based on the current block height, and * shuts down the node with an error if so (and deprecation is not disabled for - * the current client version). + * the current client version). Warning and error messages are sent to the debug + * log, the metrics UI, and (if configured) -alertnofity. + * + * fThread means run -alertnotify in a free-running thread. */ -void EnforceNodeDeprecation(int nHeight, bool forceLogging=false); +void EnforceNodeDeprecation(int nHeight, bool forceLogging=false, bool fThread=true); #endif // ZCASH_DEPRECATION_H diff --git a/src/gtest/test_deprecation.cpp b/src/gtest/test_deprecation.cpp index eb2d7bfc6..4f2526d65 100644 --- a/src/gtest/test_deprecation.cpp +++ b/src/gtest/test_deprecation.cpp @@ -1,12 +1,15 @@ #include #include +#include "chainparams.h" #include "clientversion.h" #include "deprecation.h" #include "init.h" #include "ui_interface.h" #include "util.h" -#include "chainparams.h" + +#include +#include using ::testing::StrictMock; @@ -43,6 +46,18 @@ protected: } StrictMock mock_; + + static std::vector read_lines(boost::filesystem::path filepath) { + std::vector result; + + std::ifstream f(filepath.string().c_str()); + std::string line; + while (std::getline(f,line)) { + result.push_back(line); + } + + return result; + } }; TEST_F(DeprecationTest, NonDeprecatedNodeKeepsRunning) { @@ -119,4 +134,32 @@ TEST_F(DeprecationTest, DeprecatedNodeIgnoredOnTestnet) { EXPECT_FALSE(ShutdownRequested()); EnforceNodeDeprecation(DEPRECATION_HEIGHT+1); EXPECT_FALSE(ShutdownRequested()); -} \ No newline at end of file +} + +TEST_F(DeprecationTest, AlertNotify) { + boost::filesystem::path temp = GetTempPath() / + boost::filesystem::unique_path("alertnotify-%%%%.txt"); + + mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); + + EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_WARNING)); + EnforceNodeDeprecation(DEPRECATION_HEIGHT - DEPRECATION_WARN_LIMIT, false, false); + + std::vector r = read_lines(temp); + EXPECT_EQ(r.size(), 1u); + + // -alertnotify restricts the message to safe characters. + auto expectedMsg = strprintf( + "This version will be deprecated at block height %d, and will automatically shut down. You should upgrade to the latest version of Zcash. To disable deprecation for this version, set disabledeprecation%s.", + DEPRECATION_HEIGHT, + CLIENT_VERSION_STR); + + // Windows built-in echo semantics are different than posixy shells. Quotes and + // whitespace are printed literally. +#ifndef WIN32 + EXPECT_EQ(r[0], expectedMsg); +#else + EXPECT_EQ(r[0], strprintf("'%s' ", expectedMsg)); +#endif + boost::filesystem::remove(temp); +}