LCOV - code coverage report
Current view: top level - src/test - alert_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 90 91 98.9 %
Date: 2015-10-12 22:39:14 Functions: 11 18 61.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2013 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             : // Unit tests for alert system
       6             : 
       7             : #include "alert.h"
       8             : #include "chain.h"
       9             : #include "chainparams.h"
      10             : #include "clientversion.h"
      11             : #include "data/alertTests.raw.h"
      12             : #include "main.h" // For PartitionCheck
      13             : #include "serialize.h"
      14             : #include "streams.h"
      15             : #include "util.h"
      16             : #include "utilstrencodings.h"
      17             : 
      18             : #include "test/test_bitcoin.h"
      19             : 
      20             : #include <fstream>
      21             : 
      22             : #include <boost/filesystem/operations.hpp>
      23             : #include <boost/foreach.hpp>
      24             : #include <boost/test/unit_test.hpp>
      25             : 
      26             : #if 0
      27             : //
      28             : // alertTests contains 7 alerts, generated with this code:
      29             : // (SignAndSave code not shown, alert signing key is secret)
      30             : //
      31             : {
      32             :     CAlert alert;
      33             :     alert.nRelayUntil   = 60;
      34             :     alert.nExpiration   = 24 * 60 * 60;
      35             :     alert.nID           = 1;
      36             :     alert.nCancel       = 0;   // cancels previous messages up to this ID number
      37             :     alert.nMinVer       = 0;  // These versions are protocol versions
      38             :     alert.nMaxVer       = 999001;
      39             :     alert.nPriority     = 1;
      40             :     alert.strComment    = "Alert comment";
      41             :     alert.strStatusBar  = "Alert 1";
      42             : 
      43             :     SignAndSave(alert, "test/alertTests");
      44             : 
      45             :     alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
      46             :     alert.strStatusBar  = "Alert 1 for Satoshi 0.1.0";
      47             :     SignAndSave(alert, "test/alertTests");
      48             : 
      49             :     alert.setSubVer.insert(std::string("/Satoshi:0.2.0/"));
      50             :     alert.strStatusBar  = "Alert 1 for Satoshi 0.1.0, 0.2.0";
      51             :     SignAndSave(alert, "test/alertTests");
      52             : 
      53             :     alert.setSubVer.clear();
      54             :     ++alert.nID;
      55             :     alert.nCancel = 1;
      56             :     alert.nPriority = 100;
      57             :     alert.strStatusBar  = "Alert 2, cancels 1";
      58             :     SignAndSave(alert, "test/alertTests");
      59             : 
      60             :     alert.nExpiration += 60;
      61             :     ++alert.nID;
      62             :     SignAndSave(alert, "test/alertTests");
      63             : 
      64             :     ++alert.nID;
      65             :     alert.nMinVer = 11;
      66             :     alert.nMaxVer = 22;
      67             :     SignAndSave(alert, "test/alertTests");
      68             : 
      69             :     ++alert.nID;
      70             :     alert.strStatusBar  = "Alert 2 for Satoshi 0.1.0";
      71             :     alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
      72             :     SignAndSave(alert, "test/alertTests");
      73             : 
      74             :     ++alert.nID;
      75             :     alert.nMinVer = 0;
      76             :     alert.nMaxVer = 999999;
      77             :     alert.strStatusBar  = "Evil Alert'; /bin/ls; echo '";
      78             :     alert.setSubVer.clear();
      79             :     SignAndSave(alert, "test/alertTests");
      80             : }
      81             : #endif
      82             : 
      83             : struct ReadAlerts : public TestingSetup
      84             : {
      85           3 :     ReadAlerts()
      86           3 :     {
      87           3 :         std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests));
      88             :         CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
      89             :         try {
      90          27 :             while (!stream.eof())
      91             :             {
      92          24 :                 CAlert alert;
      93             :                 stream >> alert;
      94          24 :                 alerts.push_back(alert);
      95          24 :             }
      96             :         }
      97           0 :         catch (const std::exception&) { }
      98           3 :     }
      99           3 :     ~ReadAlerts() { }
     100             : 
     101           1 :     static std::vector<std::string> read_lines(boost::filesystem::path filepath)
     102             :     {
     103             :         std::vector<std::string> result;
     104             : 
     105           3 :         std::ifstream f(filepath.string().c_str());
     106             :         std::string line;
     107          10 :         while (std::getline(f,line))
     108           4 :             result.push_back(line);
     109             : 
     110           1 :         return result;
     111             :     }
     112             : 
     113             :     std::vector<CAlert> alerts;
     114             : };
     115             : 
     116           1 : BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
     117             : 
     118             : 
     119           7 : BOOST_AUTO_TEST_CASE(AlertApplies)
     120             : {
     121           1 :     SetMockTime(11);
     122           2 :     const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
     123             : 
     124          54 :     BOOST_FOREACH(const CAlert& alert, alerts)
     125             :     {
     126          64 :         BOOST_CHECK(alert.CheckSignature(alertKey));
     127             :     }
     128             : 
     129           9 :     BOOST_CHECK(alerts.size() >= 3);
     130             : 
     131             :     // Matches:
     132          10 :     BOOST_CHECK(alerts[0].AppliesTo(1, ""));
     133          10 :     BOOST_CHECK(alerts[0].AppliesTo(999001, ""));
     134          10 :     BOOST_CHECK(alerts[0].AppliesTo(1, "/Satoshi:11.11.11/"));
     135             : 
     136          11 :     BOOST_CHECK(alerts[1].AppliesTo(1, "/Satoshi:0.1.0/"));
     137          11 :     BOOST_CHECK(alerts[1].AppliesTo(999001, "/Satoshi:0.1.0/"));
     138             : 
     139          11 :     BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.1.0/"));
     140          11 :     BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.2.0/"));
     141             : 
     142             :     // Don't match:
     143          10 :     BOOST_CHECK(!alerts[0].AppliesTo(-1, ""));
     144          10 :     BOOST_CHECK(!alerts[0].AppliesTo(999002, ""));
     145             : 
     146          11 :     BOOST_CHECK(!alerts[1].AppliesTo(1, ""));
     147          11 :     BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0"));
     148          11 :     BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.1.0"));
     149          11 :     BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0/"));
     150          11 :     BOOST_CHECK(!alerts[1].AppliesTo(-1, "/Satoshi:0.1.0/"));
     151          11 :     BOOST_CHECK(!alerts[1].AppliesTo(999002, "/Satoshi:0.1.0/"));
     152          11 :     BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.2.0/"));
     153             : 
     154          11 :     BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/"));
     155             : 
     156           1 :     SetMockTime(0);
     157           1 : }
     158             : 
     159             : 
     160           7 : BOOST_AUTO_TEST_CASE(AlertNotify)
     161             : {
     162           1 :     SetMockTime(11);
     163           2 :     const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
     164             : 
     165             :     boost::filesystem::path temp = GetTempPath() /
     166           4 :         boost::filesystem::unique_path("alertnotify-%%%%.txt");
     167             : 
     168           6 :     mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string();
     169             : 
     170          62 :     BOOST_FOREACH(CAlert alert, alerts)
     171          16 :         alert.ProcessAlert(alertKey, false);
     172             : 
     173           3 :     std::vector<std::string> r = read_lines(temp);
     174           6 :     BOOST_CHECK_EQUAL(r.size(), 4u);
     175             : 
     176             : // Windows built-in echo semantics are different than posixy shells. Quotes and
     177             : // whitespace are printed literally.
     178             : 
     179             : #ifndef WIN32
     180           5 :     BOOST_CHECK_EQUAL(r[0], "Alert 1");
     181           6 :     BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1");
     182           6 :     BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1");
     183           6 :     BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed
     184             : #else
     185             :     BOOST_CHECK_EQUAL(r[0], "'Alert 1' ");
     186             :     BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' ");
     187             :     BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' ");
     188             :     BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' ");
     189             : #endif
     190             :     boost::filesystem::remove(temp);
     191             : 
     192           1 :     SetMockTime(0);
     193           1 : }
     194             : 
     195           4 : static bool falseFunc() { return false; }
     196             : 
     197           7 : BOOST_AUTO_TEST_CASE(PartitionAlert)
     198             : {
     199             :     // Test PartitionCheck
     200             :     CCriticalSection csDummy;
     201         100 :     CBlockIndex indexDummy[100];
     202           1 :     CChainParams& params = Params(CBaseChainParams::MAIN);
     203           1 :     int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
     204             : 
     205             :     // Generate fake blockchain timestamps relative to
     206             :     // an arbitrary time:
     207           1 :     int64_t now = 1427379054;
     208           1 :     SetMockTime(now);
     209         100 :     for (int i = 0; i < 100; i++)
     210             :     {
     211         100 :         indexDummy[i].phashBlock = NULL;
     212         100 :         if (i == 0) indexDummy[i].pprev = NULL;
     213          99 :         else indexDummy[i].pprev = &indexDummy[i-1];
     214         100 :         indexDummy[i].nHeight = i;
     215         100 :         indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing;
     216             :         // Other members don't matter, the partition check code doesn't
     217             :         // use them
     218             :     }
     219             : 
     220             :     // Test 1: chain with blocks every nPowTargetSpacing seconds,
     221             :     // as normal, no worries:
     222           1 :     PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
     223           8 :     BOOST_CHECK(strMiscWarning.empty());
     224             : 
     225             :     // Test 2: go 3.5 hours without a block, expect a warning:
     226           1 :     now += 3*60*60+30*60;
     227           1 :     SetMockTime(now);
     228           1 :     PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
     229           8 :     BOOST_CHECK(!strMiscWarning.empty());
     230           7 :     BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
     231             :     strMiscWarning = "";
     232             : 
     233             :     // Test 3: test the "partition alerts only go off once per day"
     234             :     // code:
     235           1 :     now += 60*10;
     236           1 :     SetMockTime(now);
     237           1 :     PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
     238           8 :     BOOST_CHECK(strMiscWarning.empty());
     239             : 
     240             :     // Test 4: get 2.5 times as many blocks as expected:
     241           1 :     now += 60*60*24; // Pretend it is a day later
     242           1 :     SetMockTime(now);
     243           1 :     int64_t quickSpacing = nPowTargetSpacing*2/5;
     244         101 :     for (int i = 0; i < 100; i++) // Tweak chain timestamps:
     245         100 :         indexDummy[i].nTime = now - (100-i)*quickSpacing;
     246           1 :     PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
     247           8 :     BOOST_CHECK(!strMiscWarning.empty());
     248           7 :     BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
     249             :     strMiscWarning = "";
     250             : 
     251           1 :     SetMockTime(0);
     252           1 : }
     253             : 
     254           3 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.11