2018-01-02 18:12:05 +01:00
// Copyright (c) 2011-2017 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2014-03-18 10:11:00 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-10 01:57:53 +01:00
# include <util.h>
# include <clientversion.h>
# include <primitives/transaction.h>
# include <sync.h>
# include <utilstrencodings.h>
# include <utilmoneystr.h>
# include <test/test_bitcoin.h>
2013-04-13 07:13:08 +02:00
# include <stdint.h>
2011-09-28 21:35:58 +02:00
# include <vector>
2018-02-13 13:53:17 +01:00
# ifndef WIN32
2018-02-16 11:57:46 +01:00
# include <signal.h>
2018-02-13 13:53:17 +01:00
# include <sys/types.h>
# include <sys/wait.h>
# endif
2011-09-28 21:35:58 +02:00
2013-04-13 07:13:08 +02:00
# include <boost/test/unit_test.hpp>
2011-09-28 21:35:58 +02:00
2015-03-12 09:34:42 +01:00
BOOST_FIXTURE_TEST_SUITE ( util_tests , BasicTestingSetup )
2011-09-28 21:35:58 +02:00
2011-11-02 23:10:41 +01:00
BOOST_AUTO_TEST_CASE ( util_criticalsection )
{
CCriticalSection cs ;
do {
2012-04-06 18:39:12 +02:00
LOCK ( cs ) ;
break ;
2011-11-02 23:10:41 +01:00
BOOST_ERROR ( " break was swallowed! " ) ;
} while ( 0 ) ;
do {
2012-04-06 18:39:12 +02:00
TRY_LOCK ( cs , lockTest ) ;
if ( lockTest )
2011-11-02 23:10:41 +01:00
break ;
BOOST_ERROR ( " break was swallowed! " ) ;
} while ( 0 ) ;
}
2011-10-01 02:47:47 +02:00
static const unsigned char ParseHex_expected [ 65 ] = {
2013-04-28 17:37:50 +02: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-10-01 02:47:47 +02: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 ) ;
2016-02-15 15:50:28 +01:00
// Leading space must be supported (used in CDBEnv::Salvage)
result = ParseHex ( " 89 34 56 78 " ) ;
BOOST_CHECK ( result . size ( ) = = 4 & & result [ 0 ] = = 0x89 & & result [ 1 ] = = 0x34 & & result [ 2 ] = = 0x56 & & result [ 3 ] = = 0x78 ) ;
2011-10-01 02:47:47 +02: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 " ) ;
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_expected , ParseHex_expected + 5 , true ) ,
" 04 67 8a fd b0 " ) ;
2012-04-21 20:15:25 +02:00
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_expected , ParseHex_expected , true ) ,
" " ) ;
std : : vector < unsigned char > ParseHex_vec ( ParseHex_expected , ParseHex_expected + 5 ) ;
BOOST_CHECK_EQUAL (
HexStr ( ParseHex_vec , true ) ,
" 04 67 8a fd b0 " ) ;
2011-10-01 02:47:47 +02:00
}
2012-04-21 20:15:25 +02:00
2011-10-01 02:47:47 +02:00
BOOST_AUTO_TEST_CASE ( util_DateTimeStrFormat )
{
2013-01-02 01:48:28 +01:00
BOOST_CHECK_EQUAL ( DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , 0 ) , " 1970-01-01 00:00:00 " ) ;
BOOST_CHECK_EQUAL ( DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , 0x7FFFFFFF ) , " 2038-01-19 03:14:07 " ) ;
BOOST_CHECK_EQUAL ( DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , 1317425777 ) , " 2011-09-30 23:36:17 " ) ;
BOOST_CHECK_EQUAL ( DateTimeStrFormat ( " %Y-%m-%d %H:%M " , 1317425777 ) , " 2011-09-30 23:36 " ) ;
2014-05-08 18:01:10 +02:00
BOOST_CHECK_EQUAL ( DateTimeStrFormat ( " %a, %d %b %Y %H:%M:%S +0000 " , 1317425777 ) , " Fri, 30 Sep 2011 23:36:17 +0000 " ) ;
2011-10-01 02:47:47 +02:00
}
2017-05-06 01:36:47 +02:00
class TestArgsManager : public ArgsManager
{
public :
std : : map < std : : string , std : : string > & GetMapArgs ( )
{
return mapArgs ;
} ;
const std : : map < std : : string , std : : vector < std : : string > > & GetMapMultiArgs ( )
{
return mapMultiArgs ;
} ;
} ;
2011-10-01 02:47:47 +02:00
BOOST_AUTO_TEST_CASE ( util_ParseParameters )
{
2017-05-06 01:36:47 +02:00
TestArgsManager testArgs ;
2011-10-01 02:47:47 +02:00
const char * argv_test [ ] = { " -ignored " , " -a " , " -b " , " -ccc=argument " , " -ccc=multiple " , " f " , " -d=e " } ;
2017-05-06 01:36:47 +02:00
testArgs . ParseParameters ( 0 , ( char * * ) argv_test ) ;
BOOST_CHECK ( testArgs . GetMapArgs ( ) . empty ( ) & & testArgs . GetMapMultiArgs ( ) . empty ( ) ) ;
2011-10-01 02:47:47 +02:00
2017-05-06 01:36:47 +02:00
testArgs . ParseParameters ( 1 , ( char * * ) argv_test ) ;
BOOST_CHECK ( testArgs . GetMapArgs ( ) . empty ( ) & & testArgs . GetMapMultiArgs ( ) . empty ( ) ) ;
2011-10-01 02:47:47 +02:00
2017-12-12 08:39:09 +01:00
testArgs . ParseParameters ( 7 , ( char * * ) argv_test ) ;
2013-04-28 17:37:50 +02:00
// expectation: -ignored is ignored (program name argument),
2011-10-01 02:47:47 +02:00
// -a, -b and -ccc end up in map, -d ignored because it is after
// a non-option argument (non-GNU option parsing)
2017-05-06 01:36:47 +02:00
BOOST_CHECK ( testArgs . GetMapArgs ( ) . size ( ) = = 3 & & testArgs . GetMapMultiArgs ( ) . size ( ) = = 3 ) ;
BOOST_CHECK ( testArgs . IsArgSet ( " -a " ) & & testArgs . IsArgSet ( " -b " ) & & testArgs . IsArgSet ( " -ccc " )
& & ! testArgs . IsArgSet ( " f " ) & & ! testArgs . IsArgSet ( " -d " ) ) ;
BOOST_CHECK ( testArgs . GetMapMultiArgs ( ) . count ( " -a " ) & & testArgs . GetMapMultiArgs ( ) . count ( " -b " ) & & testArgs . GetMapMultiArgs ( ) . count ( " -ccc " )
& & ! testArgs . GetMapMultiArgs ( ) . count ( " f " ) & & ! testArgs . GetMapMultiArgs ( ) . count ( " -d " ) ) ;
BOOST_CHECK ( testArgs . GetMapArgs ( ) [ " -a " ] = = " " & & testArgs . GetMapArgs ( ) [ " -ccc " ] = = " multiple " ) ;
BOOST_CHECK ( testArgs . GetArgs ( " -ccc " ) . size ( ) = = 2 ) ;
2011-10-01 02:47:47 +02:00
}
BOOST_AUTO_TEST_CASE ( util_GetArg )
{
2017-05-06 01:36:47 +02:00
TestArgsManager testArgs ;
testArgs . GetMapArgs ( ) . clear ( ) ;
testArgs . GetMapArgs ( ) [ " strtest1 " ] = " string... " ;
2011-10-01 02:47:47 +02:00
// strtest2 undefined on purpose
2017-05-06 01:36:47 +02:00
testArgs . GetMapArgs ( ) [ " inttest1 " ] = " 12345 " ;
testArgs . GetMapArgs ( ) [ " inttest2 " ] = " 81985529216486895 " ;
2011-10-01 02:47:47 +02:00
// inttest3 undefined on purpose
2017-05-06 01:36:47 +02:00
testArgs . GetMapArgs ( ) [ " booltest1 " ] = " " ;
2011-10-01 02:47:47 +02:00
// booltest2 undefined on purpose
2017-05-06 01:36:47 +02:00
testArgs . GetMapArgs ( ) [ " booltest3 " ] = " 0 " ;
testArgs . GetMapArgs ( ) [ " booltest4 " ] = " 1 " ;
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 ) ;
2011-10-01 02:47:47 +02:00
}
BOOST_AUTO_TEST_CASE ( util_FormatMoney )
{
2015-06-04 14:43:02 +02: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-10-01 02:47:47 +02:00
}
BOOST_AUTO_TEST_CASE ( util_ParseMoney )
{
2014-04-23 00:46:19 +02:00
CAmount ret = 0 ;
2011-10-01 02:47:47 +02: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 17:47:55 +01:00
BOOST_CHECK ( ParseMoney ( " 1 " , ret ) ) ;
BOOST_CHECK_EQUAL ( ret , COIN ) ;
2011-10-01 02:47:47 +02: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 17:47:55 +01:00
// Parsing negative amounts must fail
BOOST_CHECK ( ! ParseMoney ( " -1 " , ret ) ) ;
2011-09-28 21:35:58 +02:00
}
2012-01-05 03:40:52 +01: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 20:10:19 +02: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-16 00:27:57 +01:00
BOOST_AUTO_TEST_CASE ( util_seed_insecure_rand )
{
2017-06-07 21:03:17 +02:00
SeedInsecureRand ( true ) ;
2013-02-16 00:27:57 +01:00
for ( int mod = 2 ; mod < 11 ; mod + + )
{
int mask = 1 ;
2017-03-21 19:49:08 +01:00
// Really rough binomial confidence approximation.
2013-02-16 00:27:57 +01: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 17:05:12 +02:00
int count = 0 ;
2013-02-16 00:27:57 +01:00
//How often does it get a zero from the uniform range [0,mod)?
2016-08-24 17:05:12 +02:00
for ( int i = 0 ; i < 10000 ; i + + ) {
2013-02-16 00:27:57 +01:00
uint32_t rval ;
do {
2017-06-07 21:03:17 +02:00
rval = InsecureRand32 ( ) & mask ;
2013-02-16 00:27:57 +01:00
} while ( rval > = ( uint32_t ) mod ) ;
count + = rval = = 0 ;
}
BOOST_CHECK ( count < = 10000 / mod + err ) ;
BOOST_CHECK ( count > = 10000 / mod - err ) ;
}
}
2013-08-08 11:58:57 +02: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 12:18:16 +01: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-19 02:43:48 +01: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 12:18:16 +01:00
size_t st = 12345678 ; /* unsigned size_t test value */
ssize_t sst = - 12345678 ; /* signed size_t test value */
2014-12-19 02:43:48 +01: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 12:18:16 +01:00
ptrdiff_t pt = 87654321 ; /* positive ptrdiff_t test value */
ptrdiff_t spt = - 87654321 ; /* negative ptrdiff_t test value */
2014-12-19 02:43:48 +01: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 12:18:16 +01:00
}
# undef B
# undef E
2014-01-09 11:35:38 +01: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 ) ;
}
2014-05-03 10:20:58 +02:00
BOOST_AUTO_TEST_CASE ( test_ParseInt32 )
{
int32_t n ;
// Valid values
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ParseInt32 ( " 1234 " , nullptr ) ) ;
2014-05-03 10:20:58 +02: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 21:19:31 +01:00
BOOST_CHECK ( ParseInt32 ( " -2147483648 " , & n ) & & n = = ( - 2147483647 - 1 ) ) ; // (-2147483647 - 1) equals INT_MIN
2014-05-03 10:20:58 +02:00
BOOST_CHECK ( ParseInt32 ( " -1234 " , & n ) & & n = = - 1234 ) ;
// Invalid values
2015-06-04 12:03:09 +02:00
BOOST_CHECK ( ! ParseInt32 ( " " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 1 " , & n ) ) ; // no padding inside
BOOST_CHECK ( ! ParseInt32 ( " 1 " , & n ) ) ;
2014-05-03 10:20:58 +02:00
BOOST_CHECK ( ! ParseInt32 ( " 1a " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " aap " , & n ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 0x1 " , & n ) ) ; // no hex
2015-06-04 12:03:09 +02: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 10:20:58 +02:00
// Overflow and underflow
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ! ParseInt32 ( " -2147483649 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 2147483648 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt32 ( " 32482348723847471234 " , nullptr ) ) ;
2014-05-03 10:20:58 +02:00
}
2015-06-04 12:03:09 +02:00
BOOST_AUTO_TEST_CASE ( test_ParseInt64 )
{
int64_t n ;
// Valid values
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ParseInt64 ( " 1234 " , nullptr ) ) ;
2015-06-04 12:03:09 +02: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 17:04:56 +02:00
BOOST_CHECK ( ParseInt64 ( " 9223372036854775807 " , & n ) & & n = = ( int64_t ) 9223372036854775807 ) ;
BOOST_CHECK ( ParseInt64 ( " -9223372036854775808 " , & n ) & & n = = ( int64_t ) - 9223372036854775807 - 1 ) ;
2015-06-04 12:03:09 +02: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 07:36:37 +02:00
BOOST_CHECK ( ! ParseInt64 ( " -9223372036854775809 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 9223372036854775808 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseInt64 ( " 32482348723847471234 " , nullptr ) ) ;
2015-06-04 12:03:09 +02:00
}
2016-06-08 10:23:25 +02:00
BOOST_AUTO_TEST_CASE ( test_ParseUInt32 )
{
uint32_t n ;
// Valid values
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ParseUInt32 ( " 1234 " , nullptr ) ) ;
2016-06-08 10:23:25 +02: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 07:36:37 +02:00
BOOST_CHECK ( ! ParseUInt32 ( " -32482348723847471234 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt32 ( " 32482348723847471234 " , nullptr ) ) ;
2016-06-08 10:23:25 +02:00
}
BOOST_AUTO_TEST_CASE ( test_ParseUInt64 )
{
uint64_t n ;
// Valid values
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ParseUInt64 ( " 1234 " , nullptr ) ) ;
2016-06-08 10:23:25 +02: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 07:36:37 +02:00
BOOST_CHECK ( ! ParseUInt64 ( " -9223372036854775809 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " 18446744073709551616 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -32482348723847471234 " , nullptr ) ) ;
2016-06-08 10:23:25 +02:00
BOOST_CHECK ( ! ParseUInt64 ( " -2147483648 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -9223372036854775808 " , & n ) ) ;
BOOST_CHECK ( ! ParseUInt64 ( " -1234 " , & n ) ) ;
}
2015-06-04 12:03:09 +02:00
BOOST_AUTO_TEST_CASE ( test_ParseDouble )
{
double n ;
// Valid values
2017-08-07 07:36:37 +02:00
BOOST_CHECK ( ParseDouble ( " 1234 " , nullptr ) ) ;
2015-06-04 12:03:09 +02: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 07:36:37 +02:00
BOOST_CHECK ( ! ParseDouble ( " -1e10000 " , nullptr ) ) ;
BOOST_CHECK ( ! ParseDouble ( " 1e10000 " , nullptr ) ) ;
2015-06-04 12:03:09 +02:00
}
2014-06-10 16:02:29 +02:00
BOOST_AUTO_TEST_CASE ( test_FormatParagraph )
{
BOOST_CHECK_EQUAL ( FormatParagraph ( " " , 79 , 0 ) , " " ) ;
BOOST_CHECK_EQUAL ( FormatParagraph ( " test " , 79 , 0 ) , " test " ) ;
2016-02-03 06:16:49 +01:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " test " , 79 , 0 ) , " test " ) ;
2014-06-10 16:02:29 +02: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 06:16:49 +01:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " testerde test " , 4 , 0 ) , " testerde \n test " ) ;
2014-06-10 16:02:29 +02:00
BOOST_CHECK_EQUAL ( FormatParagraph ( " test test " , 4 , 4 ) , " test \n test " ) ;
2016-02-03 06:16:49 +01: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 16:02:29 +02:00
}
2014-10-13 20:15:19 +02: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 12:06:00 +02:00
comments2 . push_back ( SanitizeString ( std : : string ( " Comment2; .,_?@-; ! \" #$%&'()*+/<=>[] \\ ^`{|}~ " ) , SAFE_CHARS_UA_COMMENT ) ) ; // Semicolon is discouraged but not forbidden by BIP-0014
2014-10-13 20:15:19 +02: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 12:06:00 +02:00
BOOST_CHECK_EQUAL ( FormatSubVersion ( " Test " , 99900 , comments2 ) , std : : string ( " /Test:0.9.99(comment1; Comment2; .,_?@-; )/ " ) ) ;
2014-10-13 20:15:19 +02:00
}
2015-07-06 10:49:24 +02: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 13:53:17 +01: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 ;
int rv ;
while ( true ) {
rv = read ( fd , & ch , 1 ) ; // Wait for command
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 ) ;
break ;
case ExitCommand :
close ( fd ) ;
exit ( 0 ) ;
default :
assert ( 0 ) ;
}
}
}
# endif
BOOST_AUTO_TEST_CASE ( test_LockDirectory )
{
fs : : path dirname = fs : : temp_directory_path ( ) / fs : : unique_path ( ) ;
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
// Try to aquire lock in child process while we're holding it, this should fail.
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 ) ;
// Try to acquire the lock in the child process, this should be succesful.
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 ) ;
}
2011-09-28 21:35:58 +02:00
BOOST_AUTO_TEST_SUITE_END ( )