2019-04-11 09:53:04 -04:00
// Copyright (c) 2011-2019 The Bitcoin Core developers
2014-12-13 01:09:33 -03:00
// Distributed under the MIT software license, see the accompanying
2014-03-18 06:11:00 -03:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2018-10-22 19:51:11 -03:00
# include <util/system.h>
2017-11-09 21:57:53 -03:00
# include <clientversion.h>
# include <sync.h>
2019-08-20 14:51:43 -04:00
# include <test/setup_common.h>
2019-05-06 11:52:13 -04:00
# include <test/util.h>
2018-10-22 19:51:11 -03:00
# include <util/moneystr.h>
2019-08-20 14:51:43 -04:00
# include <util/strencodings.h>
# include <util/string.h>
2019-06-24 11:22:28 -04:00
# include <util/time.h>
2013-04-13 02:13:08 -03:00
# include <stdint.h>
2019-06-24 11:22:28 -04:00
# include <thread>
2019-07-27 13:27:08 -04:00
# include <utility>
2011-09-28 16:35:58 -03:00
# include <vector>
2018-02-13 09:53:17 -03:00
# ifndef WIN32
2018-02-16 07:57:46 -03:00
# include <signal.h>
2018-02-13 09:53:17 -03:00
# include <sys/types.h>
# include <sys/wait.h>
# endif
2011-09-28 16:35:58 -03:00
2013-04-13 02:13:08 -03:00
# include <boost/test/unit_test.hpp>
2011-09-28 16:35:58 -03:00
2015-03-12 05:34:42 -03:00
BOOST_FIXTURE_TEST_SUITE ( util_tests , BasicTestingSetup )
2011-09-28 16:35:58 -03:00
2011-11-02 19:10:41 -03:00
BOOST_AUTO_TEST_CASE ( util_criticalsection )
{
CCriticalSection cs ;
do {
2012-04-06 13:39:12 -03:00
LOCK ( cs ) ;
break ;
2011-11-02 19:10:41 -03:00
BOOST_ERROR ( " break was swallowed! " ) ;
} while ( 0 ) ;
do {
2012-04-06 13:39:12 -03:00
TRY_LOCK ( cs , lockTest ) ;
2019-03-29 11:22:48 -03:00
if ( lockTest ) {
BOOST_CHECK ( true ) ; // Needed to suppress "Test case [...] did not check any assertions"
2011-11-02 19:10:41 -03:00
break ;
2019-03-29 11:22:48 -03:00
}
2011-11-02 19:10:41 -03:00
BOOST_ERROR ( " break was swallowed! " ) ;
} while ( 0 ) ;
}
2011-09-30 21:47:47 -03:00
static const unsigned char ParseHex_expected [ 65 ] = {
2013-04-28 11:37:50 -04:00
0x04 , 0x67 , 0x8a , 0xfd , 0xb0 , 0xfe , 0x55 , 0x48 , 0x27 , 0x19 , 0x67 , 0xf1 , 0xa6 , 0x71 , 0x30 , 0xb7 ,
0x10 , 0x5c , 0xd6 , 0xa8 , 0x28 , 0xe0 , 0x39 , 0x09 , 0xa6 , 0x79 , 0x62 , 0xe0 , 0xea , 0x1f , 0x61 , 0xde ,
0xb6 , 0x49 , 0xf6 , 0xbc , 0x3f , 0x4c , 0xef , 0x38 , 0xc4 , 0xf3 , 0x55 , 0x04 , 0xe5 , 0x1e , 0xc1 , 0x12 ,
0xde , 0x5c , 0x38 , 0x4d , 0xf7 , 0xba , 0x0b , 0x8d , 0x57 , 0x8a , 0x4c , 0x70 , 0x2b , 0x6b , 0xf1 , 0x1d ,
2011-09-30 21:47:47 -03:00
0x5f
} ;
BOOST_AUTO_TEST_CASE ( util_ParseHex )
{
std : : vector < unsigned char > result ;
std : : vector < unsigned char > expected ( ParseHex_expected , ParseHex_expected + sizeof ( ParseHex_expected ) ) ;
// Basic test vector
result = ParseHex ( " 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f " ) ;
BOOST_CHECK_EQUAL_COLLECTIONS ( result . begin ( ) , result . end ( ) , expected . begin ( ) , expected . end ( ) ) ;
// Spaces between bytes must be supported
result = ParseHex ( " 12 34 56 78 " ) ;
BOOST_CHECK ( result . size ( ) = = 4 & & result [ 0 ] = = 0x12 & & result [ 1 ] = = 0x34 & & result [ 2 ] = = 0x56 & & result [ 3 ] = = 0x78 ) ;
2017-12-08 08:39:22 -03:00
// Leading space must be supported (used in BerkeleyEnvironment::Salvage)
2016-02-15 11:50:28 -03:00
result = ParseHex ( " 89 34 56 78 " ) ;
BOOST_CHECK ( result . size ( ) = = 4 & & result [ 0 ] = = 0x89 & & result [ 1 ] = = 0x34 & & result [ 2 ] = = 0x56 & & result [ 3 ] = = 0x78 ) ;
2011-09-30 21:47:47 -03:00
// Stop parsing at invalid value
result = ParseHex ( " 1234 invalid 1234 " ) ;
BOOST_CHECK ( result . size ( ) = = 2 & & result [ 0 ] = = 0x12 & & result [ 1 ] = = 0x34 ) ;
}
BOOST_AUTO_TEST_CASE ( util_HexStr )
{
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_expected , ParseHex_expected + sizeof ( ParseHex_expected ) ) ,
" 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f " ) ;
2018-03-01 02:26:18 -03:00
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_expected + sizeof ( ParseHex_expected ) ,
ParseHex_expected + sizeof ( ParseHex_expected ) ) ,
" " ) ;
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_expected , ParseHex_expected ) ,
" " ) ;
2012-04-21 15:15:25 -03:00
std : : vector < unsigned char > ParseHex_vec ( ParseHex_expected , ParseHex_expected + 5 ) ;
2018-03-01 02:26:56 -03:00
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_vec . rbegin ( ) , ParseHex_vec . rend ( ) ) ,
" b0fd8a6704 "
) ;
BOOST_CHECK_EQUAL (
HexStr ( std : : reverse_iterator < const uint8_t * > ( ParseHex_expected ) ,
std : : reverse_iterator < const uint8_t * > ( ParseHex_expected ) ) ,
" "
) ;
BOOST_CHECK_EQUAL (
HexStr ( std : : reverse_iterator < const uint8_t * > ( ParseHex_expected + 1 ) ,
std : : reverse_iterator < const uint8_t * > ( ParseHex_expected ) ) ,
" 04 "
) ;
BOOST_CHECK_EQUAL (
HexStr ( std : : reverse_iterator < const uint8_t * > ( ParseHex_expected + 5 ) ,
std : : reverse_iterator < const uint8_t * > ( ParseHex_expected ) ) ,
" b0fd8a6704 "
) ;
BOOST_CHECK_EQUAL (
HexStr ( std : : reverse_iterator < const uint8_t * > ( ParseHex_expected + 65 ) ,
std : : reverse_iterator < const uint8_t * > ( ParseHex_expected ) ) ,
" 5f1df16b2b704c8a578d0bbaf74d385cde12c11ee50455f3c438ef4c3fbcf649b6de611feae06279a60939e028a8d65c10b73071a6f16719274855feb0fd8a6704 "
) ;
2011-09-30 21:47:47 -03:00
}
2019-08-20 14:51:43 -04:00
BOOST_AUTO_TEST_CASE ( util_Join )
{
// Normal version
BOOST_CHECK_EQUAL ( Join ( { } , " , " ) , " " ) ;
BOOST_CHECK_EQUAL ( Join ( { " foo " } , " , " ) , " foo " ) ;
BOOST_CHECK_EQUAL ( Join ( { " foo " , " bar " } , " , " ) , " foo, bar " ) ;
// Version with unary operator
const auto op_upper = [ ] ( const std : : string & s ) { return ToUpper ( s ) ; } ;
BOOST_CHECK_EQUAL ( Join < std : : string > ( { } , " , " , op_upper ) , " " ) ;
BOOST_CHECK_EQUAL ( Join < std : : string > ( { " foo " } , " , " , op_upper ) , " FOO " ) ;
BOOST_CHECK_EQUAL ( Join < std : : string > ( { " foo " , " bar " } , " , " , op_upper ) , " FOO, BAR " ) ;
}
2012-04-21 15:15:25 -03:00
2018-02-28 12:46:31 -03:00
BOOST_AUTO_TEST_CASE ( util_FormatISO8601DateTime )
{
BOOST_CHECK_EQUAL ( FormatISO8601DateTime ( 1317425777 ) , " 2011-09-30T23:36:17Z " ) ;
}
BOOST_AUTO_TEST_CASE ( util_FormatISO8601Date )
{
BOOST_CHECK_EQUAL ( FormatISO8601Date ( 1317425777 ) , " 2011-09-30 " ) ;
}
2018-03-21 23:24:17 -03:00
struct TestArgsManager : public ArgsManager
2017-05-05 20:36:47 -03:00
{
2018-04-04 05:08:00 -03:00
TestArgsManager ( ) { m_network_only_args . clear ( ) ; }
2018-04-04 05:01:00 -03:00
std : : map < std : : string , std : : vector < std : : string > > & GetOverrideArgs ( ) { return m_override_args ; }
std : : map < std : : string , std : : vector < std : : string > > & GetConfigArgs ( ) { return m_config_args ; }
2018-03-29 02:04:00 -03:00
void ReadConfigString ( const std : : string str_config )
{
2018-04-04 05:01:00 -03:00
std : : istringstream streamConfig ( str_config ) ;
{
LOCK ( cs_args ) ;
m_config_args . clear ( ) ;
2019-02-04 00:53:19 -03:00
m_config_sections . clear ( ) ;
2018-04-04 05:01:00 -03:00
}
2018-04-28 20:40:51 -03:00
std : : string error ;
2019-02-04 00:53:19 -03:00
BOOST_REQUIRE ( ReadConfigStream ( streamConfig , " " , error ) ) ;
2018-03-29 02:04:00 -03:00
}
2018-04-04 05:08:00 -03:00
void SetNetworkOnlyArg ( const std : : string arg )
{
LOCK ( cs_args ) ;
m_network_only_args . insert ( arg ) ;
2018-03-29 02:04:00 -03:00
}
2019-07-27 13:27:08 -04:00
void SetupArgs ( const std : : vector < std : : pair < std : : string , unsigned int > > & args )
2018-04-28 20:40:51 -03:00
{
2019-07-27 13:27:08 -04:00
for ( const auto & arg : args ) {
AddArg ( arg . first , " " , arg . second , OptionsCategory : : OPTIONS ) ;
2018-04-28 20:40:51 -03:00
}
}
2019-04-11 16:54:47 -04:00
using ArgsManager : : ReadConfigStream ;
using ArgsManager : : cs_args ;
using ArgsManager : : m_network ;
2017-05-05 20:36:47 -03:00
} ;
2011-09-30 21:47:47 -03:00
BOOST_AUTO_TEST_CASE ( util_ParseParameters )
{
2017-05-05 20:36:47 -03:00
TestArgsManager testArgs ;
2019-07-27 13:27:08 -04:00
const auto a = std : : make_pair ( " -a " , ArgsManager : : ALLOW_ANY ) ;
const auto b = std : : make_pair ( " -b " , ArgsManager : : ALLOW_ANY ) ;
const auto ccc = std : : make_pair ( " -ccc " , ArgsManager : : ALLOW_ANY ) ;
const auto d = std : : make_pair ( " -d " , ArgsManager : : ALLOW_ANY ) ;
2011-09-30 21:47:47 -03:00
const char * argv_test [ ] = { " -ignored " , " -a " , " -b " , " -ccc=argument " , " -ccc=multiple " , " f " , " -d=e " } ;
2018-04-28 20:40:51 -03:00
std : : string error ;
2019-07-27 13:27:08 -04:00
testArgs . SetupArgs ( { a , b , ccc , d } ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 0 , ( char * * ) argv_test , error ) ) ;
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) . empty ( ) & & testArgs . GetConfigArgs ( ) . empty ( ) ) ;
2011-09-30 21:47:47 -03:00
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 1 , ( char * * ) argv_test , error ) ) ;
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) . empty ( ) & & testArgs . GetConfigArgs ( ) . empty ( ) ) ;
2011-09-30 21:47:47 -03:00
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 7 , ( char * * ) argv_test , error ) ) ;
2013-04-28 11:37:50 -04:00
// expectation: -ignored is ignored (program name argument),
2011-09-30 21:47:47 -03:00
// -a, -b and -ccc end up in map, -d ignored because it is after
// a non-option argument (non-GNU option parsing)
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) . size ( ) = = 3 & & testArgs . GetConfigArgs ( ) . empty ( ) ) ;
2017-05-05 20:36:47 -03:00
BOOST_CHECK ( testArgs . IsArgSet ( " -a " ) & & testArgs . IsArgSet ( " -b " ) & & testArgs . IsArgSet ( " -ccc " )
& & ! testArgs . IsArgSet ( " f " ) & & ! testArgs . IsArgSet ( " -d " ) ) ;
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) . count ( " -a " ) & & testArgs . GetOverrideArgs ( ) . count ( " -b " ) & & testArgs . GetOverrideArgs ( ) . count ( " -ccc " )
& & ! testArgs . GetOverrideArgs ( ) . count ( " f " ) & & ! testArgs . GetOverrideArgs ( ) . count ( " -d " ) ) ;
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) [ " -a " ] . size ( ) = = 1 ) ;
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) [ " -a " ] . front ( ) = = " " ) ;
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) [ " -ccc " ] . size ( ) = = 2 ) ;
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) [ " -ccc " ] . front ( ) = = " argument " ) ;
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) [ " -ccc " ] . back ( ) = = " multiple " ) ;
2017-05-05 20:36:47 -03:00
BOOST_CHECK ( testArgs . GetArgs ( " -ccc " ) . size ( ) = = 2 ) ;
2011-09-30 21:47:47 -03:00
}
2018-03-21 23:22:52 -03:00
BOOST_AUTO_TEST_CASE ( util_GetBoolArg )
{
TestArgsManager testArgs ;
2019-07-27 13:27:08 -04:00
const auto a = std : : make_pair ( " -a " , ArgsManager : : ALLOW_BOOL ) ;
const auto b = std : : make_pair ( " -b " , ArgsManager : : ALLOW_BOOL ) ;
const auto c = std : : make_pair ( " -c " , ArgsManager : : ALLOW_BOOL ) ;
const auto d = std : : make_pair ( " -d " , ArgsManager : : ALLOW_BOOL ) ;
const auto e = std : : make_pair ( " -e " , ArgsManager : : ALLOW_BOOL ) ;
const auto f = std : : make_pair ( " -f " , ArgsManager : : ALLOW_BOOL ) ;
2018-03-21 23:22:52 -03:00
const char * argv_test [ ] = {
" ignored " , " -a " , " -nob " , " -c=0 " , " -d=1 " , " -e=false " , " -f=true " } ;
2018-04-28 20:40:51 -03:00
std : : string error ;
2019-07-27 13:27:08 -04:00
testArgs . SetupArgs ( { a , b , c , d , e , f } ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 7 , ( char * * ) argv_test , error ) ) ;
2018-03-21 23:22:52 -03:00
// Each letter should be set.
2018-06-18 01:58:28 -04:00
for ( const char opt : " abcdef " )
2018-03-21 23:22:52 -03:00
BOOST_CHECK ( testArgs . IsArgSet ( { ' - ' , opt } ) | | ! opt ) ;
// Nothing else should be in the map
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( testArgs . GetOverrideArgs ( ) . size ( ) = = 6 & &
testArgs . GetConfigArgs ( ) . empty ( ) ) ;
2018-03-21 23:22:52 -03:00
// The -no prefix should get stripped on the way in.
BOOST_CHECK ( ! testArgs . IsArgSet ( " -nob " ) ) ;
2018-03-21 23:24:17 -03:00
// The -b option is flagged as negated, and nothing else is
BOOST_CHECK ( testArgs . IsArgNegated ( " -b " ) ) ;
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -a " ) ) ;
2018-03-21 23:22:52 -03:00
// Check expected values.
BOOST_CHECK ( testArgs . GetBoolArg ( " -a " , false ) = = true ) ;
BOOST_CHECK ( testArgs . GetBoolArg ( " -b " , true ) = = false ) ;
BOOST_CHECK ( testArgs . GetBoolArg ( " -c " , true ) = = false ) ;
BOOST_CHECK ( testArgs . GetBoolArg ( " -d " , false ) = = true ) ;
BOOST_CHECK ( testArgs . GetBoolArg ( " -e " , true ) = = false ) ;
BOOST_CHECK ( testArgs . GetBoolArg ( " -f " , true ) = = false ) ;
}
2018-03-21 23:24:17 -03:00
BOOST_AUTO_TEST_CASE ( util_GetBoolArgEdgeCases )
{
// Test some awful edge cases that hopefully no user will ever exercise.
TestArgsManager testArgs ;
2018-04-04 02:26:33 -03:00
// Params test
2019-07-27 13:27:08 -04:00
const auto foo = std : : make_pair ( " -foo " , ArgsManager : : ALLOW_BOOL ) ;
const auto bar = std : : make_pair ( " -bar " , ArgsManager : : ALLOW_BOOL ) ;
2018-03-21 23:24:17 -03:00
const char * argv_test [ ] = { " ignored " , " -nofoo " , " -foo " , " -nobar=0 " } ;
2019-07-27 13:27:08 -04:00
testArgs . SetupArgs ( { foo , bar } ) ;
2018-04-28 20:40:51 -03:00
std : : string error ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 4 , ( char * * ) argv_test , error ) ) ;
2018-03-21 23:24:17 -03:00
// This was passed twice, second one overrides the negative setting.
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -foo " ) ) ;
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -foo " , " xxx " ) = = " " ) ;
2018-03-21 23:24:17 -03:00
2018-04-04 05:02:00 -03:00
// A double negative is a positive, and not marked as negated.
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -bar " ) ) ;
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -bar " , " xxx " ) = = " 1 " ) ;
// Config test
const char * conf_test = " nofoo=1 \n foo=1 \n nobar=0 \n " ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 1 , ( char * * ) argv_test , error ) ) ;
2018-04-04 02:26:33 -03:00
testArgs . ReadConfigString ( conf_test ) ;
// This was passed twice, second one overrides the negative setting,
2018-04-04 05:02:00 -03:00
// and the value.
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -foo " ) ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -foo " , " xxx " ) = = " 1 " ) ;
2018-04-04 02:26:33 -03:00
2018-04-04 05:02:00 -03:00
// A double negative is a positive, and does not count as negated.
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -bar " ) ) ;
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -bar " , " xxx " ) = = " 1 " ) ;
// Combined test
const char * combo_test_args [ ] = { " ignored " , " -nofoo " , " -bar " } ;
const char * combo_test_conf = " foo=1 \n nobar=1 \n " ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( testArgs . ParseParameters ( 3 , ( char * * ) combo_test_args , error ) ) ;
2018-04-04 02:26:33 -03:00
testArgs . ReadConfigString ( combo_test_conf ) ;
// Command line overrides, but doesn't erase old setting
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( testArgs . IsArgNegated ( " -foo " ) ) ;
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -foo " , " xxx " ) = = " 0 " ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( testArgs . GetArgs ( " -foo " ) . size ( ) = = 0 ) ;
2018-04-04 02:26:33 -03:00
// Command line overrides, but doesn't erase old setting
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( ! testArgs . IsArgNegated ( " -bar " ) ) ;
2018-04-04 02:26:33 -03:00
BOOST_CHECK ( testArgs . GetArg ( " -bar " , " xxx " ) = = " " ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( testArgs . GetArgs ( " -bar " ) . size ( ) = = 1
& & testArgs . GetArgs ( " -bar " ) . front ( ) = = " " ) ;
2018-03-21 23:24:17 -03:00
}
2018-03-29 02:04:00 -03:00
BOOST_AUTO_TEST_CASE ( util_ReadConfigStream )
{
const char * str_config =
" a= \n "
" b=1 \n "
" ccc=argument \n "
" ccc=multiple \n "
" d=e \n "
" nofff=1 \n "
" noggg=0 \n "
" h=1 \n "
" noh=1 \n "
" noi=1 \n "
2018-04-04 05:04:00 -03:00
" i=1 \n "
" sec1.ccc=extend1 \n "
" \n "
" [sec1] \n "
" ccc=extend2 \n "
2018-04-04 05:08:00 -03:00
" d=eee \n "
2018-04-04 05:04:00 -03:00
" h=1 \n "
" [sec2] \n "
" ccc=extend3 \n "
" iii=2 \n " ;
2018-03-29 02:04:00 -03:00
TestArgsManager test_args ;
2019-07-27 13:27:08 -04:00
const auto a = std : : make_pair ( " -a " , ArgsManager : : ALLOW_BOOL ) ;
const auto b = std : : make_pair ( " -b " , ArgsManager : : ALLOW_BOOL ) ;
const auto ccc = std : : make_pair ( " -ccc " , ArgsManager : : ALLOW_STRING ) ;
const auto d = std : : make_pair ( " -d " , ArgsManager : : ALLOW_STRING ) ;
const auto e = std : : make_pair ( " -e " , ArgsManager : : ALLOW_ANY ) ;
const auto fff = std : : make_pair ( " -fff " , ArgsManager : : ALLOW_BOOL ) ;
const auto ggg = std : : make_pair ( " -ggg " , ArgsManager : : ALLOW_BOOL ) ;
const auto h = std : : make_pair ( " -h " , ArgsManager : : ALLOW_BOOL ) ;
const auto i = std : : make_pair ( " -i " , ArgsManager : : ALLOW_BOOL ) ;
const auto iii = std : : make_pair ( " -iii " , ArgsManager : : ALLOW_INT ) ;
test_args . SetupArgs ( { a , b , ccc , d , e , fff , ggg , h , i , iii } ) ;
2018-03-29 02:04:00 -03:00
test_args . ReadConfigString ( str_config ) ;
// expectation: a, b, ccc, d, fff, ggg, h, i end up in map
2018-04-04 05:08:00 -03:00
// so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
2018-03-29 02:04:00 -03:00
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( test_args . GetOverrideArgs ( ) . empty ( ) ) ;
2018-04-04 05:08:00 -03:00
BOOST_CHECK ( test_args . GetConfigArgs ( ) . size ( ) = = 13 ) ;
2018-04-04 05:01:00 -03:00
BOOST_CHECK ( test_args . GetConfigArgs ( ) . count ( " -a " )
& & test_args . GetConfigArgs ( ) . count ( " -b " )
& & test_args . GetConfigArgs ( ) . count ( " -ccc " )
& & test_args . GetConfigArgs ( ) . count ( " -d " )
& & test_args . GetConfigArgs ( ) . count ( " -fff " )
& & test_args . GetConfigArgs ( ) . count ( " -ggg " )
& & test_args . GetConfigArgs ( ) . count ( " -h " )
& & test_args . GetConfigArgs ( ) . count ( " -i " )
2018-03-29 02:04:00 -03:00
) ;
2018-04-04 05:04:00 -03:00
BOOST_CHECK ( test_args . GetConfigArgs ( ) . count ( " -sec1.ccc " )
& & test_args . GetConfigArgs ( ) . count ( " -sec1.h " )
& & test_args . GetConfigArgs ( ) . count ( " -sec2.ccc " )
& & test_args . GetConfigArgs ( ) . count ( " -sec2.iii " )
2018-03-29 02:04:00 -03:00
) ;
BOOST_CHECK ( test_args . IsArgSet ( " -a " )
& & test_args . IsArgSet ( " -b " )
& & test_args . IsArgSet ( " -ccc " )
& & test_args . IsArgSet ( " -d " )
& & test_args . IsArgSet ( " -fff " )
& & test_args . IsArgSet ( " -ggg " )
& & test_args . IsArgSet ( " -h " )
& & test_args . IsArgSet ( " -i " )
& & ! test_args . IsArgSet ( " -zzz " )
2018-04-04 05:04:00 -03:00
& & ! test_args . IsArgSet ( " -iii " )
2018-03-29 02:04:00 -03:00
) ;
BOOST_CHECK ( test_args . GetArg ( " -a " , " xxx " ) = = " "
& & test_args . GetArg ( " -b " , " xxx " ) = = " 1 "
& & test_args . GetArg ( " -ccc " , " xxx " ) = = " argument "
& & test_args . GetArg ( " -d " , " xxx " ) = = " e "
& & test_args . GetArg ( " -fff " , " xxx " ) = = " 0 "
& & test_args . GetArg ( " -ggg " , " xxx " ) = = " 1 "
2018-04-04 05:02:00 -03:00
& & test_args . GetArg ( " -h " , " xxx " ) = = " 0 "
& & test_args . GetArg ( " -i " , " xxx " ) = = " 1 "
2018-03-29 02:04:00 -03:00
& & test_args . GetArg ( " -zzz " , " xxx " ) = = " xxx "
2018-04-04 05:04:00 -03:00
& & test_args . GetArg ( " -iii " , " xxx " ) = = " xxx "
2018-03-29 02:04:00 -03:00
) ;
2018-06-18 01:58:28 -04:00
for ( const bool def : { false , true } ) {
2018-03-29 02:04:00 -03:00
BOOST_CHECK ( test_args . GetBoolArg ( " -a " , def )
& & test_args . GetBoolArg ( " -b " , def )
& & ! test_args . GetBoolArg ( " -ccc " , def )
& & ! test_args . GetBoolArg ( " -d " , def )
& & ! test_args . GetBoolArg ( " -fff " , def )
& & test_args . GetBoolArg ( " -ggg " , def )
2018-04-04 05:02:00 -03:00
& & ! test_args . GetBoolArg ( " -h " , def )
& & test_args . GetBoolArg ( " -i " , def )
2018-03-29 02:04:00 -03:00
& & test_args . GetBoolArg ( " -zzz " , def ) = = def
2018-04-04 05:04:00 -03:00
& & test_args . GetBoolArg ( " -iii " , def ) = = def
2018-03-29 02:04:00 -03:00
) ;
}
BOOST_CHECK ( test_args . GetArgs ( " -a " ) . size ( ) = = 1
& & test_args . GetArgs ( " -a " ) . front ( ) = = " " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -b " ) . size ( ) = = 1
& & test_args . GetArgs ( " -b " ) . front ( ) = = " 1 " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -ccc " ) . size ( ) = = 2
& & test_args . GetArgs ( " -ccc " ) . front ( ) = = " argument "
& & test_args . GetArgs ( " -ccc " ) . back ( ) = = " multiple " ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -fff " ) . size ( ) = = 0 ) ;
2018-03-29 02:04:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -nofff " ) . size ( ) = = 0 ) ;
BOOST_CHECK ( test_args . GetArgs ( " -ggg " ) . size ( ) = = 1
& & test_args . GetArgs ( " -ggg " ) . front ( ) = = " 1 " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -noggg " ) . size ( ) = = 0 ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -h " ) . size ( ) = = 0 ) ;
2018-03-29 02:04:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -noh " ) . size ( ) = = 0 ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -i " ) . size ( ) = = 1
& & test_args . GetArgs ( " -i " ) . front ( ) = = " 1 " ) ;
2018-03-29 02:04:00 -03:00
BOOST_CHECK ( test_args . GetArgs ( " -noi " ) . size ( ) = = 0 ) ;
BOOST_CHECK ( test_args . GetArgs ( " -zzz " ) . size ( ) = = 0 ) ;
BOOST_CHECK ( ! test_args . IsArgNegated ( " -a " ) ) ;
BOOST_CHECK ( ! test_args . IsArgNegated ( " -b " ) ) ;
BOOST_CHECK ( ! test_args . IsArgNegated ( " -ccc " ) ) ;
BOOST_CHECK ( ! test_args . IsArgNegated ( " -d " ) ) ;
BOOST_CHECK ( test_args . IsArgNegated ( " -fff " ) ) ;
2018-04-04 05:02:00 -03:00
BOOST_CHECK ( ! test_args . IsArgNegated ( " -ggg " ) ) ;
2018-03-29 02:04:00 -03:00
BOOST_CHECK ( test_args . IsArgNegated ( " -h " ) ) ; // last setting takes precedence
BOOST_CHECK ( ! test_args . IsArgNegated ( " -i " ) ) ; // last setting takes precedence
BOOST_CHECK ( ! test_args . IsArgNegated ( " -zzz " ) ) ;
2018-04-04 05:04:00 -03:00
// Test sections work
test_args . SelectConfigNetwork ( " sec1 " ) ;
// same as original
BOOST_CHECK ( test_args . GetArg ( " -a " , " xxx " ) = = " "
& & test_args . GetArg ( " -b " , " xxx " ) = = " 1 "
& & test_args . GetArg ( " -fff " , " xxx " ) = = " 0 "
& & test_args . GetArg ( " -ggg " , " xxx " ) = = " 1 "
& & test_args . GetArg ( " -zzz " , " xxx " ) = = " xxx "
& & test_args . GetArg ( " -iii " , " xxx " ) = = " xxx "
) ;
2018-04-04 05:08:00 -03:00
// d is overridden
BOOST_CHECK ( test_args . GetArg ( " -d " , " xxx " ) = = " eee " ) ;
2018-04-04 05:04:00 -03:00
// section-specific setting
BOOST_CHECK ( test_args . GetArg ( " -h " , " xxx " ) = = " 1 " ) ;
// section takes priority for multiple values
BOOST_CHECK ( test_args . GetArg ( " -ccc " , " xxx " ) = = " extend1 " ) ;
// check multiple values works
const std : : vector < std : : string > sec1_ccc_expected = { " extend1 " , " extend2 " , " argument " , " multiple " } ;
const auto & sec1_ccc_res = test_args . GetArgs ( " -ccc " ) ;
BOOST_CHECK_EQUAL_COLLECTIONS ( sec1_ccc_res . begin ( ) , sec1_ccc_res . end ( ) , sec1_ccc_expected . begin ( ) , sec1_ccc_expected . end ( ) ) ;
test_args . SelectConfigNetwork ( " sec2 " ) ;
// same as original
BOOST_CHECK ( test_args . GetArg ( " -a " , " xxx " ) = = " "
& & test_args . GetArg ( " -b " , " xxx " ) = = " 1 "
& & test_args . GetArg ( " -d " , " xxx " ) = = " e "
& & test_args . GetArg ( " -fff " , " xxx " ) = = " 0 "
& & test_args . GetArg ( " -ggg " , " xxx " ) = = " 1 "
& & test_args . GetArg ( " -zzz " , " xxx " ) = = " xxx "
& & test_args . GetArg ( " -h " , " xxx " ) = = " 0 "
) ;
// section-specific setting
BOOST_CHECK ( test_args . GetArg ( " -iii " , " xxx " ) = = " 2 " ) ;
// section takes priority for multiple values
BOOST_CHECK ( test_args . GetArg ( " -ccc " , " xxx " ) = = " extend3 " ) ;
// check multiple values works
const std : : vector < std : : string > sec2_ccc_expected = { " extend3 " , " argument " , " multiple " } ;
const auto & sec2_ccc_res = test_args . GetArgs ( " -ccc " ) ;
BOOST_CHECK_EQUAL_COLLECTIONS ( sec2_ccc_res . begin ( ) , sec2_ccc_res . end ( ) , sec2_ccc_expected . begin ( ) , sec2_ccc_expected . end ( ) ) ;
2018-04-04 05:08:00 -03:00
// Test section only options
test_args . SetNetworkOnlyArg ( " -d " ) ;
test_args . SetNetworkOnlyArg ( " -ccc " ) ;
test_args . SetNetworkOnlyArg ( " -h " ) ;
test_args . SelectConfigNetwork ( CBaseChainParams : : MAIN ) ;
BOOST_CHECK ( test_args . GetArg ( " -d " , " xxx " ) = = " e " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -ccc " ) . size ( ) = = 2 ) ;
BOOST_CHECK ( test_args . GetArg ( " -h " , " xxx " ) = = " 0 " ) ;
test_args . SelectConfigNetwork ( " sec1 " ) ;
BOOST_CHECK ( test_args . GetArg ( " -d " , " xxx " ) = = " eee " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -d " ) . size ( ) = = 1 ) ;
BOOST_CHECK ( test_args . GetArgs ( " -ccc " ) . size ( ) = = 2 ) ;
BOOST_CHECK ( test_args . GetArg ( " -h " , " xxx " ) = = " 1 " ) ;
test_args . SelectConfigNetwork ( " sec2 " ) ;
BOOST_CHECK ( test_args . GetArg ( " -d " , " xxx " ) = = " xxx " ) ;
BOOST_CHECK ( test_args . GetArgs ( " -d " ) . size ( ) = = 0 ) ;
BOOST_CHECK ( test_args . GetArgs ( " -ccc " ) . size ( ) = = 1 ) ;
BOOST_CHECK ( test_args . GetArg ( " -h " , " xxx " ) = = " 0 " ) ;
2018-03-29 02:04:00 -03:00
}
2011-09-30 21:47:47 -03:00
BOOST_AUTO_TEST_CASE ( util_GetArg )
{
2017-05-05 20:36:47 -03:00
TestArgsManager testArgs ;
2018-04-04 05:01:00 -03:00
testArgs . GetOverrideArgs ( ) . clear ( ) ;
testArgs . GetOverrideArgs ( ) [ " strtest1 " ] = { " string... " } ;
2011-09-30 21:47:47 -03:00
// strtest2 undefined on purpose
2018-04-04 05:01:00 -03:00
testArgs . GetOverrideArgs ( ) [ " inttest1 " ] = { " 12345 " } ;
testArgs . GetOverrideArgs ( ) [ " inttest2 " ] = { " 81985529216486895 " } ;
2011-09-30 21:47:47 -03:00
// inttest3 undefined on purpose
2018-04-04 05:01:00 -03:00
testArgs . GetOverrideArgs ( ) [ " booltest1 " ] = { " " } ;
2011-09-30 21:47:47 -03:00
// booltest2 undefined on purpose
2018-04-04 05:01:00 -03:00
testArgs . GetOverrideArgs ( ) [ " booltest3 " ] = { " 0 " } ;
testArgs . GetOverrideArgs ( ) [ " booltest4 " ] = { " 1 " } ;
// priorities
testArgs . GetOverrideArgs ( ) [ " pritest1 " ] = { " a " , " b " } ;
testArgs . GetConfigArgs ( ) [ " pritest2 " ] = { " a " , " b " } ;
testArgs . GetOverrideArgs ( ) [ " pritest3 " ] = { " a " } ;
testArgs . GetConfigArgs ( ) [ " pritest3 " ] = { " b " } ;
testArgs . GetOverrideArgs ( ) [ " pritest4 " ] = { " a " , " b " } ;
testArgs . GetConfigArgs ( ) [ " pritest4 " ] = { " c " , " d " } ;
2017-05-05 20:36:47 -03:00
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " strtest1 " , " default " ) , " string... " ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " strtest2 " , " default " ) , " default " ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " inttest1 " , - 1 ) , 12345 ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " inttest2 " , - 1 ) , 81985529216486895LL ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " inttest3 " , - 1 ) , - 1 ) ;
BOOST_CHECK_EQUAL ( testArgs . GetBoolArg ( " booltest1 " , false ) , true ) ;
BOOST_CHECK_EQUAL ( testArgs . GetBoolArg ( " booltest2 " , false ) , false ) ;
BOOST_CHECK_EQUAL ( testArgs . GetBoolArg ( " booltest3 " , false ) , false ) ;
BOOST_CHECK_EQUAL ( testArgs . GetBoolArg ( " booltest4 " , false ) , true ) ;
2018-04-04 05:01:00 -03:00
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " pritest1 " , " default " ) , " b " ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " pritest2 " , " default " ) , " a " ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " pritest3 " , " default " ) , " a " ) ;
BOOST_CHECK_EQUAL ( testArgs . GetArg ( " pritest4 " , " default " ) , " b " ) ;
2011-09-30 21:47:47 -03:00
}
2018-03-29 02:01:00 -03:00
BOOST_AUTO_TEST_CASE ( util_GetChainName )
{
TestArgsManager test_args ;
2019-07-27 13:27:08 -04:00
const auto testnet = std : : make_pair ( " -testnet " , ArgsManager : : ALLOW_BOOL ) ;
const auto regtest = std : : make_pair ( " -regtest " , ArgsManager : : ALLOW_BOOL ) ;
test_args . SetupArgs ( { testnet , regtest } ) ;
2018-03-29 02:01:00 -03:00
const char * argv_testnet [ ] = { " cmd " , " -testnet " } ;
const char * argv_regtest [ ] = { " cmd " , " -regtest " } ;
const char * argv_test_no_reg [ ] = { " cmd " , " -testnet " , " -noregtest " } ;
const char * argv_both [ ] = { " cmd " , " -testnet " , " -regtest " } ;
2018-03-29 02:05:00 -03:00
// equivalent to "-testnet"
2018-04-04 05:10:00 -03:00
// regtest in testnet section is ignored
const char * testnetconf = " testnet=1 \n regtest=0 \n [test] \n regtest=1 " ;
2018-04-28 20:40:51 -03:00
std : : string error ;
2018-03-29 02:05:00 -03:00
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 0 , ( char * * ) argv_testnet , error ) ) ;
2018-03-29 02:01:00 -03:00
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " main " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_testnet , error ) ) ;
2018-03-29 02:01:00 -03:00
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_regtest , error ) ) ;
2018-03-29 02:01:00 -03:00
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " regtest " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 3 , ( char * * ) argv_test_no_reg , error ) ) ;
2018-03-29 02:01:00 -03:00
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 3 , ( char * * ) argv_both , error ) ) ;
2018-03-29 02:01:00 -03:00
BOOST_CHECK_THROW ( test_args . GetChainName ( ) , std : : runtime_error ) ;
2018-03-29 02:05:00 -03:00
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 0 , ( char * * ) argv_testnet , error ) ) ;
2018-03-29 02:05:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_testnet , error ) ) ;
2018-03-29 02:05:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_regtest , error ) ) ;
2018-03-29 02:05:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_THROW ( test_args . GetChainName ( ) , std : : runtime_error ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 3 , ( char * * ) argv_test_no_reg , error ) ) ;
2018-03-29 02:05:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 3 , ( char * * ) argv_both , error ) ) ;
2018-03-29 02:05:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_THROW ( test_args . GetChainName ( ) , std : : runtime_error ) ;
2018-04-04 05:10:00 -03:00
// check setting the network to test (and thus making
2018-04-22 07:53:35 -03:00
// [test] regtest=1 potentially relevant) doesn't break things
2018-04-04 05:10:00 -03:00
test_args . SelectConfigNetwork ( " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 0 , ( char * * ) argv_testnet , error ) ) ;
2018-04-04 05:10:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_testnet , error ) ) ;
2018-04-04 05:10:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_regtest , error ) ) ;
2018-04-04 05:10:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_THROW ( test_args . GetChainName ( ) , std : : runtime_error ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 2 , ( char * * ) argv_test_no_reg , error ) ) ;
2018-04-04 05:10:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_EQUAL ( test_args . GetChainName ( ) , " test " ) ;
2018-08-02 10:31:10 -04:00
BOOST_CHECK ( test_args . ParseParameters ( 3 , ( char * * ) argv_both , error ) ) ;
2018-04-04 05:10:00 -03:00
test_args . ReadConfigString ( testnetconf ) ;
BOOST_CHECK_THROW ( test_args . GetChainName ( ) , std : : runtime_error ) ;
2018-03-29 02:01:00 -03:00
}
2019-04-11 16:54:47 -04:00
// Test different ways settings can be merged, and verify results. This test can
// be used to confirm that updates to settings code don't change behavior
2019-04-24 05:57:34 -04:00
// unintentionally.
2019-04-11 16:54:47 -04:00
//
// The test covers:
//
// - Combining different setting actions. Possible actions are: configuring a
// setting, negating a setting (adding "-no" prefix), and configuring/negating
// settings in a network section (adding "main." or "test." prefixes).
//
// - Combining settings from command line arguments and a config file.
//
// - Combining SoftSet and ForceSet calls.
//
// - Testing "main" and "test" network values to make sure settings from network
// sections are applied and to check for mainnet-specific behaviors like
// inheriting settings from the default section.
//
// - Testing network-specific settings like "-wallet", that may be ignored
// outside a network section, and non-network specific settings like "-server"
// that aren't sensitive to the network.
//
2019-05-06 17:12:42 -04:00
struct ArgsMergeTestingSetup : public BasicTestingSetup {
2019-04-11 16:54:47 -04:00
//! Max number of actions to sequence together. Can decrease this when
//! debugging to make test results easier to understand.
static constexpr int MAX_ACTIONS = 3 ;
2019-05-06 11:52:13 -04:00
enum Action { NONE , SET , NEGATE , SECTION_SET , SECTION_NEGATE } ;
2019-04-11 16:54:47 -04:00
using ActionList = Action [ MAX_ACTIONS ] ;
//! Enumerate all possible test configurations.
template < typename Fn >
void ForEachMergeSetup ( Fn & & fn )
{
2019-05-06 11:52:13 -04:00
ActionList arg_actions = { } ;
ForEachNoDup ( arg_actions , SET , SECTION_NEGATE , [ & ] {
ActionList conf_actions = { } ;
ForEachNoDup ( conf_actions , SET , SECTION_NEGATE , [ & ] {
2019-04-11 16:54:47 -04:00
for ( bool soft_set : { false , true } ) {
for ( bool force_set : { false , true } ) {
for ( const std : : string & section : { CBaseChainParams : : MAIN , CBaseChainParams : : TESTNET } ) {
for ( const std : : string & network : { CBaseChainParams : : MAIN , CBaseChainParams : : TESTNET } ) {
for ( bool net_specific : { false , true } ) {
fn ( arg_actions , conf_actions , soft_set , force_set , section , network , net_specific ) ;
}
}
}
}
}
} ) ;
} ) ;
}
//! Translate actions into a list of <key>=<value> setting strings.
std : : vector < std : : string > GetValues ( const ActionList & actions ,
const std : : string & section ,
const std : : string & name ,
const std : : string & value_prefix )
{
std : : vector < std : : string > values ;
int suffix = 0 ;
for ( Action action : actions ) {
2019-05-06 11:52:13 -04:00
if ( action = = NONE ) break ;
2019-04-11 16:54:47 -04:00
std : : string prefix ;
if ( action = = SECTION_SET | | action = = SECTION_NEGATE ) prefix = section + " . " ;
if ( action = = SET | | action = = SECTION_SET ) {
for ( int i = 0 ; i < 2 ; + + i ) {
values . push_back ( prefix + name + " = " + value_prefix + std : : to_string ( + + suffix ) ) ;
}
}
if ( action = = NEGATE | | action = = SECTION_NEGATE ) {
values . push_back ( prefix + " no " + name + " =1 " ) ;
}
}
return values ;
}
} ;
// Regression test covering different ways config settings can be merged. The
// test parses and merges settings, representing the results as strings that get
// compared against an expected hash. To debug, the result strings can be dumped
2019-04-24 05:57:34 -04:00
// to a file (see comments below).
2019-05-06 17:12:42 -04:00
BOOST_FIXTURE_TEST_CASE ( util_ArgsMerge , ArgsMergeTestingSetup )
2019-04-11 16:54:47 -04:00
{
CHash256 out_sha ;
FILE * out_file = nullptr ;
2019-05-06 17:12:42 -04:00
if ( const char * out_path = getenv ( " ARGS_MERGE_TEST_OUT " ) ) {
2019-04-11 16:54:47 -04:00
out_file = fsbridge : : fopen ( out_path , " w " ) ;
if ( ! out_file ) throw std : : system_error ( errno , std : : generic_category ( ) , " fopen failed " ) ;
}
ForEachMergeSetup ( [ & ] ( const ActionList & arg_actions , const ActionList & conf_actions , bool soft_set , bool force_set ,
const std : : string & section , const std : : string & network , bool net_specific ) {
TestArgsManager parser ;
LOCK ( parser . cs_args ) ;
std : : string desc = " net= " ;
desc + = network ;
parser . m_network = network ;
2019-04-24 05:57:34 -04:00
const std : : string & name = net_specific ? " wallet " : " server " ;
2019-04-11 16:54:47 -04:00
const std : : string key = " - " + name ;
scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
2019-07-27 05:06:32 -04:00
parser . AddArg ( key , name , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2019-04-11 16:54:47 -04:00
if ( net_specific ) parser . SetNetworkOnlyArg ( key ) ;
auto args = GetValues ( arg_actions , section , name , " a " ) ;
std : : vector < const char * > argv = { " ignored " } ;
for ( auto & arg : args ) {
arg . insert ( 0 , " - " ) ;
desc + = " " ;
desc + = arg ;
argv . push_back ( arg . c_str ( ) ) ;
}
std : : string error ;
BOOST_CHECK ( parser . ParseParameters ( argv . size ( ) , argv . data ( ) , error ) ) ;
BOOST_CHECK_EQUAL ( error , " " ) ;
std : : string conf ;
for ( auto & conf_val : GetValues ( conf_actions , section , name , " c " ) ) {
desc + = " " ;
desc + = conf_val ;
conf + = conf_val ;
conf + = " \n " ;
}
std : : istringstream conf_stream ( conf ) ;
BOOST_CHECK ( parser . ReadConfigStream ( conf_stream , " filepath " , error ) ) ;
BOOST_CHECK_EQUAL ( error , " " ) ;
if ( soft_set ) {
desc + = " soft " ;
parser . SoftSetArg ( key , " soft1 " ) ;
parser . SoftSetArg ( key , " soft2 " ) ;
}
if ( force_set ) {
desc + = " force " ;
parser . ForceSetArg ( key , " force1 " ) ;
parser . ForceSetArg ( key , " force2 " ) ;
}
desc + = " || " ;
if ( ! parser . IsArgSet ( key ) ) {
desc + = " unset " ;
BOOST_CHECK ( ! parser . IsArgNegated ( key ) ) ;
BOOST_CHECK_EQUAL ( parser . GetArg ( key , " default " ) , " default " ) ;
BOOST_CHECK ( parser . GetArgs ( key ) . empty ( ) ) ;
} else if ( parser . IsArgNegated ( key ) ) {
desc + = " negated " ;
BOOST_CHECK_EQUAL ( parser . GetArg ( key , " default " ) , " 0 " ) ;
BOOST_CHECK ( parser . GetArgs ( key ) . empty ( ) ) ;
} else {
desc + = parser . GetArg ( key , " default " ) ;
desc + = " | " ;
for ( const auto & arg : parser . GetArgs ( key ) ) {
desc + = " " ;
desc + = arg ;
}
}
std : : set < std : : string > ignored = parser . GetUnsuitableSectionOnlyArgs ( ) ;
if ( ! ignored . empty ( ) ) {
desc + = " | ignored " ;
for ( const auto & arg : ignored ) {
desc + = " " ;
desc + = arg ;
}
}
desc + = " \n " ;
out_sha . Write ( ( const unsigned char * ) desc . data ( ) , desc . size ( ) ) ;
if ( out_file ) {
BOOST_REQUIRE ( fwrite ( desc . data ( ) , 1 , desc . size ( ) , out_file ) = = desc . size ( ) ) ;
}
} ) ;
if ( out_file ) {
if ( fclose ( out_file ) ) throw std : : system_error ( errno , std : : generic_category ( ) , " fclose failed " ) ;
out_file = nullptr ;
}
unsigned char out_sha_bytes [ CSHA256 : : OUTPUT_SIZE ] ;
out_sha . Finalize ( out_sha_bytes ) ;
std : : string out_sha_hex = HexStr ( std : : begin ( out_sha_bytes ) , std : : end ( out_sha_bytes ) ) ;
// If check below fails, should manually dump the results with:
//
2019-05-06 17:12:42 -04:00
// ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ArgsMerge
2019-04-11 16:54:47 -04:00
//
// And verify diff against previous results to make sure the changes are expected.
//
// Results file is formatted like:
//
// <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
2019-05-06 11:52:13 -04:00
BOOST_CHECK_EQUAL ( out_sha_hex , " b835eef5977d69114eb039a976201f8c7121f34fe2b7ea2b73cafb516e5c9dc8 " ) ;
2019-04-11 16:54:47 -04:00
}
2019-05-06 17:12:42 -04:00
// Similar test as above, but for ArgsManager::GetChainName function.
struct ChainMergeTestingSetup : public BasicTestingSetup {
static constexpr int MAX_ACTIONS = 2 ;
enum Action { NONE , ENABLE_TEST , DISABLE_TEST , NEGATE_TEST , ENABLE_REG , DISABLE_REG , NEGATE_REG } ;
using ActionList = Action [ MAX_ACTIONS ] ;
//! Enumerate all possible test configurations.
template < typename Fn >
void ForEachMergeSetup ( Fn & & fn )
{
ActionList arg_actions = { } ;
ForEachNoDup ( arg_actions , ENABLE_TEST , NEGATE_REG , [ & ] {
ActionList conf_actions = { } ;
ForEachNoDup ( conf_actions , ENABLE_TEST , NEGATE_REG , [ & ] { fn ( arg_actions , conf_actions ) ; } ) ;
} ) ;
}
} ;
BOOST_FIXTURE_TEST_CASE ( util_ChainMerge , ChainMergeTestingSetup )
{
CHash256 out_sha ;
FILE * out_file = nullptr ;
if ( const char * out_path = getenv ( " CHAIN_MERGE_TEST_OUT " ) ) {
out_file = fsbridge : : fopen ( out_path , " w " ) ;
if ( ! out_file ) throw std : : system_error ( errno , std : : generic_category ( ) , " fopen failed " ) ;
}
ForEachMergeSetup ( [ & ] ( const ActionList & arg_actions , const ActionList & conf_actions ) {
TestArgsManager parser ;
LOCK ( parser . cs_args ) ;
scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
2019-07-27 05:06:32 -04:00
parser . AddArg ( " -regtest " , " regtest " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
parser . AddArg ( " -testnet " , " testnet " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2019-05-06 17:12:42 -04:00
auto arg = [ ] ( Action action ) { return action = = ENABLE_TEST ? " -testnet=1 " :
action = = DISABLE_TEST ? " -testnet=0 " :
action = = NEGATE_TEST ? " -notestnet=1 " :
action = = ENABLE_REG ? " -regtest=1 " :
action = = DISABLE_REG ? " -regtest=0 " :
action = = NEGATE_REG ? " -noregtest=1 " : nullptr ; } ;
std : : string desc ;
std : : vector < const char * > argv = { " ignored " } ;
for ( Action action : arg_actions ) {
const char * argstr = arg ( action ) ;
if ( ! argstr ) break ;
argv . push_back ( argstr ) ;
desc + = " " ;
desc + = argv . back ( ) ;
}
std : : string error ;
BOOST_CHECK ( parser . ParseParameters ( argv . size ( ) , argv . data ( ) , error ) ) ;
BOOST_CHECK_EQUAL ( error , " " ) ;
std : : string conf ;
for ( Action action : conf_actions ) {
const char * argstr = arg ( action ) ;
if ( ! argstr ) break ;
desc + = " " ;
desc + = argstr + 1 ;
conf + = argstr + 1 ;
}
std : : istringstream conf_stream ( conf ) ;
BOOST_CHECK ( parser . ReadConfigStream ( conf_stream , " filepath " , error ) ) ;
BOOST_CHECK_EQUAL ( error , " " ) ;
desc + = " || " ;
try {
desc + = parser . GetChainName ( ) ;
} catch ( const std : : runtime_error & e ) {
desc + = " error: " ;
desc + = e . what ( ) ;
}
desc + = " \n " ;
out_sha . Write ( ( const unsigned char * ) desc . data ( ) , desc . size ( ) ) ;
if ( out_file ) {
BOOST_REQUIRE ( fwrite ( desc . data ( ) , 1 , desc . size ( ) , out_file ) = = desc . size ( ) ) ;
}
} ) ;
if ( out_file ) {
if ( fclose ( out_file ) ) throw std : : system_error ( errno , std : : generic_category ( ) , " fclose failed " ) ;
out_file = nullptr ;
}
unsigned char out_sha_bytes [ CSHA256 : : OUTPUT_SIZE ] ;
out_sha . Finalize ( out_sha_bytes ) ;
std : : string out_sha_hex = HexStr ( std : : begin ( out_sha_bytes ) , std : : end ( out_sha_bytes ) ) ;
// If check below fails, should manually dump the results with:
//
// CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ChainMerge
//
// And verify diff against previous results to make sure the changes are expected.
//
// Results file is formatted like:
//
// <input> || <output>
BOOST_CHECK_EQUAL ( out_sha_hex , " b284f4b4a15dd6bf8c06213a69a004b1960388e1d9917173927db52ac220927f " ) ;
}
2011-09-30 21:47:47 -03:00
BOOST_AUTO_TEST_CASE ( util_FormatMoney )
{
2015-06-04 09:43:02 -03:00
BOOST_CHECK_EQUAL ( FormatMoney ( 0 ) , " 0.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( ( COIN / 10000 ) * 123456789 ) , " 12345.6789 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( - COIN ) , " -1.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 100000000 ) , " 100000000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 10000000 ) , " 10000000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 1000000 ) , " 1000000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 100000 ) , " 100000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 10000 ) , " 10000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 1000 ) , " 1000.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 100 ) , " 100.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN * 10 ) , " 10.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN ) , " 1.00 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 10 ) , " 0.10 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 100 ) , " 0.01 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 1000 ) , " 0.001 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 10000 ) , " 0.0001 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 100000 ) , " 0.00001 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 1000000 ) , " 0.000001 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 10000000 ) , " 0.0000001 " ) ;
BOOST_CHECK_EQUAL ( FormatMoney ( COIN / 100000000 ) , " 0.00000001 " ) ;
2011-09-30 21:47:47 -03:00
}
BOOST_AUTO_TEST_CASE ( util_ParseMoney )
{
2014-04-22 19:46:19 -03:00
CAmount ret = 0 ;
2011-09-30 21:47:47 -03:00
BOOST_CHECK ( ParseMoney ( " 0.0 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , 0 ) ;
BOOST_CHECK ( ParseMoney ( " 12345.6789 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , ( COIN / 10000 ) * 123456789 ) ;
BOOST_CHECK ( ParseMoney ( " 100000000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 100000000 ) ;
BOOST_CHECK ( ParseMoney ( " 10000000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 10000000 ) ;
BOOST_CHECK ( ParseMoney ( " 1000000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 1000000 ) ;
BOOST_CHECK ( ParseMoney ( " 100000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 100000 ) ;
BOOST_CHECK ( ParseMoney ( " 10000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 10000 ) ;
BOOST_CHECK ( ParseMoney ( " 1000.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 1000 ) ;
BOOST_CHECK ( ParseMoney ( " 100.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 100 ) ;
BOOST_CHECK ( ParseMoney ( " 10.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN * 10 ) ;
BOOST_CHECK ( ParseMoney ( " 1.00 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN ) ;
2016-01-19 13:47:55 -03:00
BOOST_CHECK ( ParseMoney ( " 1 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN ) ;
2011-09-30 21:47:47 -03:00
BOOST_CHECK ( ParseMoney ( " 0.1 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 10 ) ;
BOOST_CHECK ( ParseMoney ( " 0.01 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 100 ) ;
BOOST_CHECK ( ParseMoney ( " 0.001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 1000 ) ;
BOOST_CHECK ( ParseMoney ( " 0.0001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 10000 ) ;
BOOST_CHECK ( ParseMoney ( " 0.00001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 100000 ) ;
BOOST_CHECK ( ParseMoney ( " 0.000001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 1000000 ) ;
BOOST_CHECK ( ParseMoney ( " 0.0000001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 10000000 ) ;
BOOST_CHECK ( ParseMoney ( " 0.00000001 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN / 100000000 ) ;
// Attempted 63 bit overflow should fail
BOOST_CHECK ( ! ParseMoney ( " 92233720368.54775808 " , ret ) ) ;
2016-01-19 13:47:55 -03:00
// Parsing negative amounts must fail
BOOST_CHECK ( ! ParseMoney ( " -1 " , ret ) ) ;
2011-09-28 16:35:58 -03:00
}
2012-01-04 23:40:52 -03:00
BOOST_AUTO_TEST_CASE ( util_IsHex )
{
BOOST_CHECK ( IsHex ( " 00 " ) ) ;
BOOST_CHECK ( IsHex ( " 00112233445566778899aabbccddeeffAABBCCDDEEFF " ) ) ;
BOOST_CHECK ( IsHex ( " ff " ) ) ;
BOOST_CHECK ( IsHex ( " FF " ) ) ;
BOOST_CHECK ( ! IsHex ( " " ) ) ;
BOOST_CHECK ( ! IsHex ( " 0 " ) ) ;
BOOST_CHECK ( ! IsHex ( " a " ) ) ;
BOOST_CHECK ( ! IsHex ( " eleven " ) ) ;
BOOST_CHECK ( ! IsHex ( " 00xx00 " ) ) ;
BOOST_CHECK ( ! IsHex ( " 0x0000 " ) ) ;
}
2017-05-07 15:10:19 -03:00
BOOST_AUTO_TEST_CASE ( util_IsHexNumber )
{
BOOST_CHECK ( IsHexNumber ( " 0x0 " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 0 " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 0x10 " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 10 " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 0xff " ) ) ;
BOOST_CHECK ( IsHexNumber ( " ff " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 0xFfa " ) ) ;
BOOST_CHECK ( IsHexNumber ( " Ffa " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 0x00112233445566778899aabbccddeeffAABBCCDDEEFF " ) ) ;
BOOST_CHECK ( IsHexNumber ( " 00112233445566778899aabbccddeeffAABBCCDDEEFF " ) ) ;
BOOST_CHECK ( ! IsHexNumber ( " " ) ) ; // empty string not allowed
BOOST_CHECK ( ! IsHexNumber ( " 0x " ) ) ; // empty string after prefix not allowed
BOOST_CHECK ( ! IsHexNumber ( " 0x0 " ) ) ; // no spaces at end,
BOOST_CHECK ( ! IsHexNumber ( " 0x0 " ) ) ; // or beginning,
BOOST_CHECK ( ! IsHexNumber ( " 0x 0 " ) ) ; // or middle,
BOOST_CHECK ( ! IsHexNumber ( " " ) ) ; // etc.
BOOST_CHECK ( ! IsHexNumber ( " 0x0ga " ) ) ; // invalid character
BOOST_CHECK ( ! IsHexNumber ( " x0 " ) ) ; // broken prefix
BOOST_CHECK ( ! IsHexNumber ( " 0x0x00 " ) ) ; // two prefixes not allowed
}
2013-02-15 20:27:57 -03:00
BOOST_AUTO_TEST_CASE ( util_seed_insecure_rand )
{
2017-06-07 15:03:17 -04:00
SeedInsecureRand ( true ) ;
2013-02-15 20:27:57 -03:00
for ( int mod = 2 ; mod < 11 ; mod + + )
{
int mask = 1 ;
2017-03-21 15:49:08 -03:00
// Really rough binomial confidence approximation.
2013-02-15 20:27:57 -03:00
int err = 30 * 10000. / mod * sqrt ( ( 1. / mod * ( 1 - 1. / mod ) ) / 10000. ) ;
//mask is 2^ceil(log2(mod))-1
while ( mask < mod - 1 ) mask = ( mask < < 1 ) + 1 ;
2016-08-24 12:05:12 -03:00
int count = 0 ;
2013-02-15 20:27:57 -03:00
//How often does it get a zero from the uniform range [0,mod)?
2016-08-24 12:05:12 -03:00
for ( int i = 0 ; i < 10000 ; i + + ) {
2013-02-15 20:27:57 -03:00
uint32_t rval ;
do {
2017-06-07 15:03:17 -04:00
rval = InsecureRand32 ( ) & mask ;
2013-02-15 20:27:57 -03:00
} while ( rval > = ( uint32_t ) mod ) ;
count + = rval = = 0 ;
}
BOOST_CHECK ( count < = 10000 / mod + err ) ;
BOOST_CHECK ( count > = 10000 / mod - err ) ;
}
}
2013-08-08 05:58:57 -04:00
BOOST_AUTO_TEST_CASE ( util_TimingResistantEqual )
{
BOOST_CHECK ( TimingResistantEqual ( std : : string ( " " ) , std : : string ( " " ) ) ) ;
BOOST_CHECK ( ! TimingResistantEqual ( std : : string ( " abc " ) , std : : string ( " " ) ) ) ;
BOOST_CHECK ( ! TimingResistantEqual ( std : : string ( " " ) , std : : string ( " abc " ) ) ) ;
BOOST_CHECK ( ! TimingResistantEqual ( std : : string ( " a " ) , std : : string ( " aa " ) ) ) ;
BOOST_CHECK ( ! TimingResistantEqual ( std : : string ( " aa " ) , std : : string ( " a " ) ) ) ;
BOOST_CHECK ( TimingResistantEqual ( std : : string ( " abc " ) , std : : string ( " abc " ) ) ) ;
BOOST_CHECK ( ! TimingResistantEqual ( std : : string ( " abc " ) , std : : string ( " aba " ) ) ) ;
}
2013-11-13 08:18:16 -03:00
/* Test strprintf formatting directives.
* Put a string before and after to ensure sanity of element sizes on stack . */
# define B "check_prefix"
# define E "check_postfix"
BOOST_AUTO_TEST_CASE ( strprintf_numbers )
{
int64_t s64t = - 9223372036854775807LL ; /* signed 64 bit test value */
uint64_t u64t = 18446744073709551615ULL ; /* unsigned 64 bit test value */
2014-12-18 22:43:48 -03:00
BOOST_CHECK ( strprintf ( " %s %d %s " , B , s64t , E ) = = B " -9223372036854775807 " E ) ;
BOOST_CHECK ( strprintf ( " %s %u %s " , B , u64t , E ) = = B " 18446744073709551615 " E ) ;
BOOST_CHECK ( strprintf ( " %s %x %s " , B , u64t , E ) = = B " ffffffffffffffff " E ) ;
2013-11-13 08:18:16 -03:00
size_t st = 12345678 ; /* unsigned size_t test value */
ssize_t sst = - 12345678 ; /* signed size_t test value */
2014-12-18 22:43:48 -03:00
BOOST_CHECK ( strprintf ( " %s %d %s " , B , sst , E ) = = B " -12345678 " E ) ;
BOOST_CHECK ( strprintf ( " %s %u %s " , B , st , E ) = = B " 12345678 " E ) ;
BOOST_CHECK ( strprintf ( " %s %x %s " , B , st , E ) = = B " bc614e " E ) ;
2013-11-13 08:18:16 -03:00
ptrdiff_t pt = 87654321 ; /* positive ptrdiff_t test value */
ptrdiff_t spt = - 87654321 ; /* negative ptrdiff_t test value */
2014-12-18 22:43:48 -03:00
BOOST_CHECK ( strprintf ( " %s %d %s " , B , spt , E ) = = B " -87654321 " E ) ;
BOOST_CHECK ( strprintf ( " %s %u %s " , B , pt , E ) = = B " 87654321 " E ) ;
BOOST_CHECK ( strprintf ( " %s %x %s " , B , pt , E ) = = B " 5397fb1 " E ) ;
2013-11-13 08:18:16 -03:00
}
# undef B
# undef E
2014-01-09 07:35:38 -03:00
/* Check for mingw/wine issue #3494
* Remove this test before time . ctime ( 0xffffffff ) = = ' Sun Feb 7 07 : 28 : 15 2106 '
*/
BOOST_AUTO_TEST_CASE ( gettime )
{
BOOST_CHECK ( ( GetTime ( ) & ~ 0xFFFFFFFFLL ) = = 0 ) ;
}
2019-05-18 17:44:39 -04:00
BOOST_AUTO_TEST_CASE ( util_time_GetTime )
{
SetMockTime ( 111 ) ;
// Check that mock time does not change after a sleep
for ( const auto & num_sleep : { 0 , 1 } ) {
MilliSleep ( num_sleep ) ;
BOOST_CHECK_EQUAL ( 111 , GetTime ( ) ) ; // Deprecated time getter
BOOST_CHECK_EQUAL ( 111 , GetTime < std : : chrono : : seconds > ( ) . count ( ) ) ;
BOOST_CHECK_EQUAL ( 111000 , GetTime < std : : chrono : : milliseconds > ( ) . count ( ) ) ;
BOOST_CHECK_EQUAL ( 111000000 , GetTime < std : : chrono : : microseconds > ( ) . count ( ) ) ;
}
SetMockTime ( 0 ) ;
// Check that system time changes after a sleep
const auto ms_0 = GetTime < std : : chrono : : milliseconds > ( ) ;
const auto us_0 = GetTime < std : : chrono : : microseconds > ( ) ;
MilliSleep ( 1 ) ;
BOOST_CHECK ( ms_0 < GetTime < std : : chrono : : milliseconds > ( ) ) ;
BOOST_CHECK ( us_0 < GetTime < std : : chrono : : microseconds > ( ) ) ;
}
2018-07-22 15:34:45 -04:00
BOOST_AUTO_TEST_CASE ( test_IsDigit )
{
BOOST_CHECK_EQUAL ( IsDigit ( ' 0 ' ) , true ) ;
BOOST_CHECK_EQUAL ( IsDigit ( ' 1 ' ) , true ) ;
BOOST_CHECK_EQUAL ( IsDigit ( ' 8 ' ) , true ) ;
BOOST_CHECK_EQUAL ( IsDigit ( ' 9 ' ) , true ) ;
BOOST_CHECK_EQUAL ( IsDigit ( ' 0 ' - 1 ) , false ) ;
BOOST_CHECK_EQUAL ( IsDigit ( ' 9 ' + 1 ) , false ) ;
BOOST_CHECK_EQUAL ( IsDigit ( 0 ) , false ) ;
BOOST_CHECK_EQUAL ( IsDigit ( 1 ) , false ) ;
BOOST_CHECK_EQUAL ( IsDigit ( 8 ) , false ) ;
BOOST_CHECK_EQUAL ( IsDigit ( 9 ) , false ) ;
}
2014-05-03 04:20:58 -04:00
BOOST_AUTO_TEST_CASE ( test_ParseInt32 )
{
int32_t n ;
// Valid values
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ParseInt32 ( " 1234 " , nullptr ) ) ;
2014-05-03 04:20:58 -04:00
BOOST_CHECK ( ParseInt32 ( " 0 " , & n ) & & n = = 0 ) ;
BOOST_CHECK ( ParseInt32 ( " 1234 " , & n ) & & n = = 1234 ) ;
BOOST_CHECK ( ParseInt32 ( " 01234 " , & n ) & & n = = 1234 ) ; // no octal
BOOST_CHECK ( ParseInt32 ( " 2147483647 " , & n ) & & n = = 2147483647 ) ;
2017-03-07 17:19:31 -03:00
BOOST_CHECK ( ParseInt32 ( " -2147483648 " , & n ) & & n = = ( - 2147483647 - 1 ) ) ; // (-2147483647 - 1) equals INT_MIN
2014-05-03 04:20:58 -04:00
BOOST_CHECK ( ParseInt32 ( " -1234 " , & n ) & & n = = - 1234 ) ;
// Invalid values
2015-06-04 07:03:09 -03:00
BOOST_CHECK ( ! ParseInt32 ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseInt32 ( " 1 " , & n ) ) ;
2014-05-03 04:20:58 -04:00
BOOST_CHECK ( ! ParseInt32 ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 0x1 " , & n ) ) ; // no hex
2015-06-04 07:03:09 -03:00
BOOST_CHECK ( ! ParseInt32 ( " 0x1 " , & n ) ) ; // no hex
const char test_bytes [ ] = { ' 1 ' , 0 , ' 1 ' } ;
std : : string teststr ( test_bytes , sizeof ( test_bytes ) ) ;
BOOST_CHECK ( ! ParseInt32 ( teststr , & n ) ) ; // no embedded NULs
2014-05-03 04:20:58 -04:00
// Overflow and underflow
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! ParseInt32 ( " -2147483649 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 2147483648 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 32482348723847471234 " , nullptr ) ) ;
2014-05-03 04:20:58 -04:00
}
2015-06-04 07:03:09 -03:00
BOOST_AUTO_TEST_CASE ( test_ParseInt64 )
{
int64_t n ;
// Valid values
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ParseInt64 ( " 1234 " , nullptr ) ) ;
2015-06-04 07:03:09 -03:00
BOOST_CHECK ( ParseInt64 ( " 0 " , & n ) & & n = = 0LL ) ;
BOOST_CHECK ( ParseInt64 ( " 1234 " , & n ) & & n = = 1234LL ) ;
BOOST_CHECK ( ParseInt64 ( " 01234 " , & n ) & & n = = 1234LL ) ; // no octal
BOOST_CHECK ( ParseInt64 ( " 2147483647 " , & n ) & & n = = 2147483647LL ) ;
BOOST_CHECK ( ParseInt64 ( " -2147483648 " , & n ) & & n = = - 2147483648LL ) ;
2015-06-05 12:04:56 -03:00
BOOST_CHECK ( ParseInt64 ( " 9223372036854775807 " , & n ) & & n = = ( int64_t ) 9223372036854775807 ) ;
BOOST_CHECK ( ParseInt64 ( " -9223372036854775808 " , & n ) & & n = = ( int64_t ) - 9223372036854775807 - 1 ) ;
2015-06-04 07:03:09 -03:00
BOOST_CHECK ( ParseInt64 ( " -1234 " , & n ) & & n = = - 1234LL ) ;
// Invalid values
BOOST_CHECK ( ! ParseInt64 ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseInt64 ( " 1 " , & n ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 0x1 " , & n ) ) ; // no hex
const char test_bytes [ ] = { ' 1 ' , 0 , ' 1 ' } ;
std : : string teststr ( test_bytes , sizeof ( test_bytes ) ) ;
BOOST_CHECK ( ! ParseInt64 ( teststr , & n ) ) ; // no embedded NULs
// Overflow and underflow
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! ParseInt64 ( " -9223372036854775809 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 9223372036854775808 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 32482348723847471234 " , nullptr ) ) ;
2015-06-04 07:03:09 -03:00
}
2016-06-08 04:23:25 -04:00
BOOST_AUTO_TEST_CASE ( test_ParseUInt32 )
{
uint32_t n ;
// Valid values
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ParseUInt32 ( " 1234 " , nullptr ) ) ;
2016-06-08 04:23:25 -04:00
BOOST_CHECK ( ParseUInt32 ( " 0 " , & n ) & & n = = 0 ) ;
BOOST_CHECK ( ParseUInt32 ( " 1234 " , & n ) & & n = = 1234 ) ;
BOOST_CHECK ( ParseUInt32 ( " 01234 " , & n ) & & n = = 1234 ) ; // no octal
BOOST_CHECK ( ParseUInt32 ( " 2147483647 " , & n ) & & n = = 2147483647 ) ;
BOOST_CHECK ( ParseUInt32 ( " 2147483648 " , & n ) & & n = = ( uint32_t ) 2147483648 ) ;
BOOST_CHECK ( ParseUInt32 ( " 4294967295 " , & n ) & & n = = ( uint32_t ) 4294967295 ) ;
// Invalid values
BOOST_CHECK ( ! ParseUInt32 ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseUInt32 ( " -1 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 1 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 0x1 " , & n ) ) ; // no hex
BOOST_CHECK ( ! ParseUInt32 ( " 0x1 " , & n ) ) ; // no hex
const char test_bytes [ ] = { ' 1 ' , 0 , ' 1 ' } ;
std : : string teststr ( test_bytes , sizeof ( test_bytes ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( teststr , & n ) ) ; // no embedded NULs
// Overflow and underflow
BOOST_CHECK ( ! ParseUInt32 ( " -2147483648 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 4294967296 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " -1234 " , & n ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! ParseUInt32 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 32482348723847471234 " , nullptr ) ) ;
2016-06-08 04:23:25 -04:00
}
BOOST_AUTO_TEST_CASE ( test_ParseUInt64 )
{
uint64_t n ;
// Valid values
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ParseUInt64 ( " 1234 " , nullptr ) ) ;
2016-06-08 04:23:25 -04:00
BOOST_CHECK ( ParseUInt64 ( " 0 " , & n ) & & n = = 0LL ) ;
BOOST_CHECK ( ParseUInt64 ( " 1234 " , & n ) & & n = = 1234LL ) ;
BOOST_CHECK ( ParseUInt64 ( " 01234 " , & n ) & & n = = 1234LL ) ; // no octal
BOOST_CHECK ( ParseUInt64 ( " 2147483647 " , & n ) & & n = = 2147483647LL ) ;
BOOST_CHECK ( ParseUInt64 ( " 9223372036854775807 " , & n ) & & n = = 9223372036854775807ULL ) ;
BOOST_CHECK ( ParseUInt64 ( " 9223372036854775808 " , & n ) & & n = = 9223372036854775808ULL ) ;
BOOST_CHECK ( ParseUInt64 ( " 18446744073709551615 " , & n ) & & n = = 18446744073709551615ULL ) ;
// Invalid values
BOOST_CHECK ( ! ParseUInt64 ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseUInt64 ( " -1 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 1 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 0x1 " , & n ) ) ; // no hex
const char test_bytes [ ] = { ' 1 ' , 0 , ' 1 ' } ;
std : : string teststr ( test_bytes , sizeof ( test_bytes ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( teststr , & n ) ) ; // no embedded NULs
// Overflow and underflow
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! ParseUInt64 ( " -9223372036854775809 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 18446744073709551616 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -32482348723847471234 " , nullptr ) ) ;
2016-06-08 04:23:25 -04:00
BOOST_CHECK ( ! ParseUInt64 ( " -2147483648 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -9223372036854775808 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -1234 " , & n ) ) ;
}
2015-06-04 07:03:09 -03:00
BOOST_AUTO_TEST_CASE ( test_ParseDouble )
{
double n ;
// Valid values
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ParseDouble ( " 1234 " , nullptr ) ) ;
2015-06-04 07:03:09 -03:00
BOOST_CHECK ( ParseDouble ( " 0 " , & n ) & & n = = 0.0 ) ;
BOOST_CHECK ( ParseDouble ( " 1234 " , & n ) & & n = = 1234.0 ) ;
BOOST_CHECK ( ParseDouble ( " 01234 " , & n ) & & n = = 1234.0 ) ; // no octal
BOOST_CHECK ( ParseDouble ( " 2147483647 " , & n ) & & n = = 2147483647.0 ) ;
BOOST_CHECK ( ParseDouble ( " -2147483648 " , & n ) & & n = = - 2147483648.0 ) ;
BOOST_CHECK ( ParseDouble ( " -1234 " , & n ) & & n = = - 1234.0 ) ;
BOOST_CHECK ( ParseDouble ( " 1e6 " , & n ) & & n = = 1e6 ) ;
BOOST_CHECK ( ParseDouble ( " -1e6 " , & n ) & & n = = - 1e6 ) ;
// Invalid values
BOOST_CHECK ( ! ParseDouble ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseDouble ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseDouble ( " 1 " , & n ) ) ;
BOOST_CHECK ( ! ParseDouble ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseDouble ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseDouble ( " 0x1 " , & n ) ) ; // no hex
const char test_bytes [ ] = { ' 1 ' , 0 , ' 1 ' } ;
std : : string teststr ( test_bytes , sizeof ( test_bytes ) ) ;
BOOST_CHECK ( ! ParseDouble ( teststr , & n ) ) ; // no embedded NULs
// Overflow and underflow
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! ParseDouble ( " -1e10000 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseDouble ( " 1e10000 " , nullptr ) ) ;
2015-06-04 07:03:09 -03:00
}
2014-06-10 10:02:29 -04:00
BOOST_AUTO_TEST_CASE ( test_FormatParagraph )
{
BOOST_CHECK_EQUAL ( FormatParagraph ( " " , 79 , 0 ) , " " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " test " , 79 , 0 ) , " test " ) ;
2016-02-03 02:16:49 -03:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " test " , 79 , 0 ) , " test " ) ;
2014-06-10 10:02:29 -04:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " test test " , 79 , 0 ) , " test test " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " test test " , 4 , 0 ) , " test \n test " ) ;
2016-02-03 02:16:49 -03:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " testerde test " , 4 , 0 ) , " testerde \n test " ) ;
2014-06-10 10:02:29 -04:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " test test " , 4 , 4 ) , " test \n test " ) ;
2016-02-03 02:16:49 -03:00
// Make sure we don't indent a fully-new line following a too-long line ending
BOOST_CHECK_EQUAL ( FormatParagraph ( " test test \n abc " , 4 , 4 ) , " test \n test \n abc " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length until it gets here " , 79 ) , " This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length \n until it gets here " ) ;
// Test wrap length is exact
BOOST_CHECK_EQUAL ( FormatParagraph ( " a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p " , 79 ) , " a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de \n f g h i j k l m n o p " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " x \n a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p " , 79 ) , " x \n a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de \n f g h i j k l m n o p " ) ;
// Indent should be included in length of lines
BOOST_CHECK_EQUAL ( FormatParagraph ( " x \n a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg h i j k " , 79 , 4 ) , " x \n a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de \n f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg \n h i j k " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " This is a very long test string. This is a second sentence in the very long test string. " , 79 ) , " This is a very long test string. This is a second sentence in the very long \n test string. " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " This is a very long test string. \n This is a second sentence in the very long test string. This is a third sentence in the very long test string. " , 79 ) , " This is a very long test string. \n This is a second sentence in the very long test string. This is a third \n sentence in the very long test string. " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " This is a very long test string. \n \n This is a second sentence in the very long test string. This is a third sentence in the very long test string. " , 79 ) , " This is a very long test string. \n \n This is a second sentence in the very long test string. This is a third \n sentence in the very long test string. " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " Testing that normal newlines do not get indented. \n Like here. " , 79 ) , " Testing that normal newlines do not get indented. \n Like here. " ) ;
2014-06-10 10:02:29 -04:00
}
2014-10-13 15:15:19 -03:00
BOOST_AUTO_TEST_CASE ( test_FormatSubVersion )
{
std : : vector < std : : string > comments ;
comments . push_back ( std : : string ( " comment1 " ) ) ;
std : : vector < std : : string > comments2 ;
comments2 . push_back ( std : : string ( " comment1 " ) ) ;
2015-09-23 07:06:00 -03:00
comments2 . push_back ( SanitizeString ( std : : string ( " Comment2; .,_?@-; ! \" #$%&'()*+/<=>[] \\ ^`{|}~ " ) , SAFE_CHARS_UA_COMMENT ) ) ; // Semicolon is discouraged but not forbidden by BIP-0014
2014-10-13 15:15:19 -03:00
BOOST_CHECK_EQUAL ( FormatSubVersion ( " Test " , 99900 , std : : vector < std : : string > ( ) ) , std : : string ( " /Test:0.9.99/ " ) ) ;
BOOST_CHECK_EQUAL ( FormatSubVersion ( " Test " , 99900 , comments ) , std : : string ( " /Test:0.9.99(comment1)/ " ) ) ;
2015-09-23 07:06:00 -03:00
BOOST_CHECK_EQUAL ( FormatSubVersion ( " Test " , 99900 , comments2 ) , std : : string ( " /Test:0.9.99(comment1; Comment2; .,_?@-; )/ " ) ) ;
2014-10-13 15:15:19 -03:00
}
2015-07-06 05:49:24 -03:00
BOOST_AUTO_TEST_CASE ( test_ParseFixedPoint )
{
int64_t amount = 0 ;
BOOST_CHECK ( ParseFixedPoint ( " 0 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 0LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 100000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 0.0 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 0LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " -0.1 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , - 10000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1.1 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 110000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1.10000000000000000 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 110000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1.1e1 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 1100000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1.1e-1 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 11000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1000 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 100000000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " -1000 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , - 100000000000LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 0.00000001 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 1LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 0.0000000100000000 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 1LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " -0.00000001 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , - 1LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 1000000000.00000001 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 100000000000000001LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " 9999999999.99999999 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , 999999999999999999LL ) ;
BOOST_CHECK ( ParseFixedPoint ( " -9999999999.99999999 " , 8 , & amount ) ) ;
BOOST_CHECK_EQUAL ( amount , - 999999999999999999LL ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " - " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " a-1000 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -a1000 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -1000a " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -01000 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 00.1 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " .1 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " --0.1 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 0.000000001 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -0.000000001 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 0.00000001000000001 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -10000000000.00000000 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 10000000000.00000000 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -10000000000.00000001 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 10000000000.00000001 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -10000000000.00000009 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 10000000000.00000009 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -99999999999.99999999 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 99999909999.09999999 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 92233720368.54775807 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 92233720368.54775808 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -92233720368.54775808 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " -92233720368.54775809 " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 1.1e " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 1.1e- " , 8 , & amount ) ) ;
BOOST_CHECK ( ! ParseFixedPoint ( " 1. " , 8 , & amount ) ) ;
}
2018-02-13 09:53:17 -03:00
static void TestOtherThread ( fs : : path dirname , std : : string lockname , bool * result )
{
* result = LockDirectory ( dirname , lockname ) ;
}
# ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
static constexpr char LockCommand = ' L ' ;
static constexpr char UnlockCommand = ' U ' ;
static constexpr char ExitCommand = ' X ' ;
static void TestOtherProcess ( fs : : path dirname , std : : string lockname , int fd )
{
char ch ;
while ( true ) {
2018-03-25 17:49:33 -03:00
int rv = read ( fd , & ch , 1 ) ; // Wait for command
2018-02-13 09:53:17 -03:00
assert ( rv = = 1 ) ;
switch ( ch ) {
case LockCommand :
ch = LockDirectory ( dirname , lockname ) ;
rv = write ( fd , & ch , 1 ) ;
assert ( rv = = 1 ) ;
break ;
case UnlockCommand :
ReleaseDirectoryLocks ( ) ;
ch = true ; // Always succeeds
rv = write ( fd , & ch , 1 ) ;
2018-04-12 03:25:45 -03:00
assert ( rv = = 1 ) ;
2018-02-13 09:53:17 -03:00
break ;
case ExitCommand :
close ( fd ) ;
exit ( 0 ) ;
default :
assert ( 0 ) ;
}
}
}
# endif
BOOST_AUTO_TEST_CASE ( test_LockDirectory )
{
2019-06-19 17:52:35 -04:00
fs : : path dirname = GetDataDir ( ) / " lock_dir " ;
2018-02-13 09:53:17 -03:00
const std : : string lockname = " .lock " ;
# ifndef WIN32
// Revert SIGCHLD to default, otherwise boost.test will catch and fail on
// it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
// at build-time of the boost library
void ( * old_handler ) ( int ) = signal ( SIGCHLD , SIG_DFL ) ;
// Fork another process for testing before creating the lock, so that we
// won't fork while holding the lock (which might be undefined, and is not
// relevant as test case as that is avoided with -daemonize).
int fd [ 2 ] ;
BOOST_CHECK_EQUAL ( socketpair ( AF_UNIX , SOCK_STREAM , 0 , fd ) , 0 ) ;
pid_t pid = fork ( ) ;
if ( ! pid ) {
BOOST_CHECK_EQUAL ( close ( fd [ 1 ] ) , 0 ) ; // Child: close parent end
TestOtherProcess ( dirname , lockname , fd [ 0 ] ) ;
}
BOOST_CHECK_EQUAL ( close ( fd [ 0 ] ) , 0 ) ; // Parent: close child end
# endif
// Lock on non-existent directory should fail
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname ) , false ) ;
fs : : create_directories ( dirname ) ;
// Probing lock on new directory should succeed
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname , true ) , true ) ;
// Persistent lock on new directory should succeed
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname ) , true ) ;
// Another lock on the directory from the same thread should succeed
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname ) , true ) ;
// Another lock on the directory from a different thread within the same process should succeed
bool threadresult ;
std : : thread thr ( TestOtherThread , dirname , lockname , & threadresult ) ;
thr . join ( ) ;
BOOST_CHECK_EQUAL ( threadresult , true ) ;
# ifndef WIN32
2018-02-26 16:19:29 -03:00
// Try to acquire lock in child process while we're holding it, this should fail.
2018-02-13 09:53:17 -03:00
char ch ;
BOOST_CHECK_EQUAL ( write ( fd [ 1 ] , & LockCommand , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( read ( fd [ 1 ] , & ch , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( ( bool ) ch , false ) ;
// Give up our lock
ReleaseDirectoryLocks ( ) ;
// Probing lock from our side now should succeed, but not hold on to the lock.
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname , true ) , true ) ;
2018-02-26 16:19:29 -03:00
// Try to acquire the lock in the child process, this should be successful.
2018-02-13 09:53:17 -03:00
BOOST_CHECK_EQUAL ( write ( fd [ 1 ] , & LockCommand , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( read ( fd [ 1 ] , & ch , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( ( bool ) ch , true ) ;
// When we try to probe the lock now, it should fail.
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname , true ) , false ) ;
// Unlock the lock in the child process
BOOST_CHECK_EQUAL ( write ( fd [ 1 ] , & UnlockCommand , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( read ( fd [ 1 ] , & ch , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( ( bool ) ch , true ) ;
// When we try to probe the lock now, it should succeed.
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname , true ) , true ) ;
// Re-lock the lock in the child process, then wait for it to exit, check
// successful return. After that, we check that exiting the process
// has released the lock as we would expect by probing it.
int processstatus ;
BOOST_CHECK_EQUAL ( write ( fd [ 1 ] , & LockCommand , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( write ( fd [ 1 ] , & ExitCommand , 1 ) , 1 ) ;
BOOST_CHECK_EQUAL ( waitpid ( pid , & processstatus , 0 ) , pid ) ;
BOOST_CHECK_EQUAL ( processstatus , 0 ) ;
BOOST_CHECK_EQUAL ( LockDirectory ( dirname , lockname , true ) , true ) ;
// Restore SIGCHLD
signal ( SIGCHLD , old_handler ) ;
BOOST_CHECK_EQUAL ( close ( fd [ 1 ] ) , 0 ) ; // Close our side of the socketpair
# endif
// Clean up
ReleaseDirectoryLocks ( ) ;
fs : : remove_all ( dirname ) ;
}
2018-03-07 08:08:55 -03:00
BOOST_AUTO_TEST_CASE ( test_DirIsWritable )
{
2018-07-11 23:44:12 -04:00
// Should be able to write to the data dir.
2019-06-19 17:52:35 -04:00
fs : : path tmpdirname = GetDataDir ( ) ;
2018-03-07 08:08:55 -03:00
BOOST_CHECK_EQUAL ( DirIsWritable ( tmpdirname ) , true ) ;
// Should not be able to write to a non-existent dir.
2018-07-11 23:44:12 -04:00
tmpdirname = tmpdirname / fs : : unique_path ( ) ;
2018-03-07 08:08:55 -03:00
BOOST_CHECK_EQUAL ( DirIsWritable ( tmpdirname ) , false ) ;
fs : : create_directory ( tmpdirname ) ;
// Should be able to write to it now.
BOOST_CHECK_EQUAL ( DirIsWritable ( tmpdirname ) , true ) ;
fs : : remove ( tmpdirname ) ;
}
2018-08-28 13:42:27 -03:00
BOOST_AUTO_TEST_CASE ( test_ToLower )
{
BOOST_CHECK_EQUAL ( ToLower ( ' @ ' ) , ' @ ' ) ;
BOOST_CHECK_EQUAL ( ToLower ( ' A ' ) , ' a ' ) ;
BOOST_CHECK_EQUAL ( ToLower ( ' Z ' ) , ' z ' ) ;
BOOST_CHECK_EQUAL ( ToLower ( ' [ ' ) , ' [ ' ) ;
BOOST_CHECK_EQUAL ( ToLower ( 0 ) , 0 ) ;
2019-01-09 21:46:32 -03:00
BOOST_CHECK_EQUAL ( ToLower ( ' \xff ' ) , ' \xff ' ) ;
2018-08-28 13:42:27 -03:00
2019-08-07 00:42:54 -04:00
BOOST_CHECK_EQUAL ( ToLower ( " " ) , " " ) ;
BOOST_CHECK_EQUAL ( ToLower ( " #HODL " ) , " #hodl " ) ;
BOOST_CHECK_EQUAL ( ToLower ( " \x00 \xfe \xff " ) , " \x00 \xfe \xff " ) ;
2018-08-28 13:42:27 -03:00
}
BOOST_AUTO_TEST_CASE ( test_ToUpper )
{
BOOST_CHECK_EQUAL ( ToUpper ( ' ` ' ) , ' ` ' ) ;
BOOST_CHECK_EQUAL ( ToUpper ( ' a ' ) , ' A ' ) ;
BOOST_CHECK_EQUAL ( ToUpper ( ' z ' ) , ' Z ' ) ;
BOOST_CHECK_EQUAL ( ToUpper ( ' { ' ) , ' { ' ) ;
BOOST_CHECK_EQUAL ( ToUpper ( 0 ) , 0 ) ;
2019-01-09 21:46:32 -03:00
BOOST_CHECK_EQUAL ( ToUpper ( ' \xff ' ) , ' \xff ' ) ;
2019-08-07 00:42:54 -04:00
BOOST_CHECK_EQUAL ( ToUpper ( " " ) , " " ) ;
BOOST_CHECK_EQUAL ( ToUpper ( " #hodl " ) , " #HODL " ) ;
BOOST_CHECK_EQUAL ( ToUpper ( " \x00 \xfe \xff " ) , " \x00 \xfe \xff " ) ;
2018-08-28 13:42:27 -03:00
}
BOOST_AUTO_TEST_CASE ( test_Capitalize )
{
BOOST_CHECK_EQUAL ( Capitalize ( " " ) , " " ) ;
BOOST_CHECK_EQUAL ( Capitalize ( " bitcoin " ) , " Bitcoin " ) ;
BOOST_CHECK_EQUAL ( Capitalize ( " \x00 \xfe \xff " ) , " \x00 \xfe \xff " ) ;
}
2011-09-28 16:35:58 -03:00
BOOST_AUTO_TEST_SUITE_END ( )