2014-02-17 21:07:09 +00:00
/*
This file is part of cpp - ethereum .
cpp - ethereum is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
cpp - ethereum is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with cpp - ethereum . If not , see < http : //www.gnu.org/licenses/>.
*/
2014-09-27 10:51:34 +00:00
/** @file vm.cpp
2014-02-17 21:07:09 +00:00
* @ author Gav Wood < i @ gavwood . com >
* @ date 2014
2014-09-27 10:51:34 +00:00
* vm test functions .
2014-02-17 21:07:09 +00:00
*/
2014-10-29 10:29:34 +00:00
# include <chrono>
2014-11-07 12:29:13 +00:00
# include <boost/filesystem.hpp>
2014-12-05 16:00:29 +00:00
# include <libethereum/Executive.h>
2014-12-10 16:41:53 +00:00
# include <libevm/VMFactory.h>
2014-10-27 17:59:42 +00:00
# include "vm.h"
2014-09-25 09:18:32 +00:00
2014-02-17 21:07:09 +00:00
using namespace std ;
2014-02-21 19:18:30 +00:00
using namespace json_spirit ;
2014-09-05 15:09:58 +00:00
using namespace dev ;
using namespace dev : : eth ;
2014-09-27 10:51:34 +00:00
using namespace dev : : test ;
2014-02-17 21:07:09 +00:00
2014-10-08 15:51:51 +00:00
FakeExtVM : : FakeExtVM ( eth : : BlockInfo const & _previousBlock , eth : : BlockInfo const & _currentBlock , unsigned _depth ) : /// TODO: XXX: remove the default argument & fix.
2015-01-09 09:58:32 +00:00
ExtVMFace ( Address ( ) , Address ( ) , Address ( ) , 0 , 1 , bytesConstRef ( ) , bytes ( ) , _previousBlock , _currentBlock , test : : lastHashes ( _currentBlock . number ) , _depth ) { }
2014-10-01 11:59:07 +00:00
2014-12-12 12:33:42 +00:00
h160 FakeExtVM : : create ( u256 _endowment , u256 & io_gas , bytesConstRef _init , OnOpFunc const & )
2014-02-17 21:07:09 +00:00
{
2014-10-29 16:25:02 +00:00
Address na = right160 ( sha3 ( rlpList ( myAddress , get < 1 > ( addresses [ myAddress ] ) ) ) ) ;
2014-09-25 09:18:32 +00:00
2014-12-12 12:33:42 +00:00
Transaction t ( _endowment , gasPrice , io_gas , _init . toBytes ( ) ) ;
2014-10-06 19:42:41 +00:00
callcreates . push_back ( t ) ;
2014-10-29 16:25:02 +00:00
return na ;
2014-09-27 10:51:34 +00:00
}
2014-03-24 23:51:40 +00:00
2014-12-12 12:33:42 +00:00
bool FakeExtVM : : call ( Address _receiveAddress , u256 _value , bytesConstRef _data , u256 & io_gas , bytesRef _out , OnOpFunc const & , Address _myAddressOverride , Address _codeAddressOverride )
2014-09-27 10:51:34 +00:00
{
2014-12-12 12:33:42 +00:00
Transaction t ( _value , gasPrice , io_gas , _receiveAddress , _data . toVector ( ) ) ;
2014-10-06 19:42:41 +00:00
callcreates . push_back ( t ) ;
2014-10-29 16:25:02 +00:00
( void ) _out ;
2014-11-03 15:33:02 +00:00
( void ) _myAddressOverride ;
( void ) _codeAddressOverride ;
2014-09-27 10:51:34 +00:00
return true ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : setTransaction ( Address _caller , u256 _value , u256 _gasPrice , bytes const & _data )
{
caller = origin = _caller ;
value = _value ;
data = & ( thisTxData = _data ) ;
gasPrice = _gasPrice ;
}
2014-10-01 11:59:07 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : setContract ( Address _myAddress , u256 _myBalance , u256 _myNonce , map < u256 , u256 > const & _storage , bytes const & _code )
{
myAddress = _myAddress ;
set ( myAddress , _myBalance , _myNonce , _storage , _code ) ;
}
2014-10-01 11:59:07 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : set ( Address _a , u256 _myBalance , u256 _myNonce , map < u256 , u256 > const & _storage , bytes const & _code )
{
get < 0 > ( addresses [ _a ] ) = _myBalance ;
get < 1 > ( addresses [ _a ] ) = _myNonce ;
get < 2 > ( addresses [ _a ] ) = _storage ;
get < 3 > ( addresses [ _a ] ) = _code ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : reset ( u256 _myBalance , u256 _myNonce , map < u256 , u256 > const & _storage )
{
callcreates . clear ( ) ;
addresses . clear ( ) ;
set ( myAddress , _myBalance , _myNonce , _storage , get < 3 > ( addresses [ myAddress ] ) ) ;
}
void FakeExtVM : : push ( mObject & o , string const & _n , u256 _v )
{
o [ _n ] = toString ( _v ) ;
}
2014-06-27 19:39:46 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : push ( mArray & a , u256 _v )
{
a . push_back ( toString ( _v ) ) ;
}
mObject FakeExtVM : : exportEnv ( )
{
mObject ret ;
ret [ " previousHash " ] = toString ( previousBlock . hash ) ;
push ( ret , " currentDifficulty " , currentBlock . difficulty ) ;
push ( ret , " currentTimestamp " , currentBlock . timestamp ) ;
ret [ " currentCoinbase " ] = toString ( currentBlock . coinbaseAddress ) ;
push ( ret , " currentNumber " , currentBlock . number ) ;
push ( ret , " currentGasLimit " , currentBlock . gasLimit ) ;
return ret ;
}
void FakeExtVM : : importEnv ( mObject & _o )
{
2014-10-14 13:13:38 +00:00
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert ( _o . count ( " previousHash " ) > 0 ) ;
assert ( _o . count ( " currentGasLimit " ) > 0 ) ;
assert ( _o . count ( " currentDifficulty " ) > 0 ) ;
assert ( _o . count ( " currentTimestamp " ) > 0 ) ;
assert ( _o . count ( " currentCoinbase " ) > 0 ) ;
assert ( _o . count ( " currentNumber " ) > 0 ) ;
2014-09-27 10:51:34 +00:00
previousBlock . hash = h256 ( _o [ " previousHash " ] . get_str ( ) ) ;
currentBlock . number = toInt ( _o [ " currentNumber " ] ) ;
2015-01-09 09:58:32 +00:00
lastHashes = test : : lastHashes ( currentBlock . number ) ;
2014-09-27 10:51:34 +00:00
currentBlock . gasLimit = toInt ( _o [ " currentGasLimit " ] ) ;
currentBlock . difficulty = toInt ( _o [ " currentDifficulty " ] ) ;
currentBlock . timestamp = toInt ( _o [ " currentTimestamp " ] ) ;
currentBlock . coinbaseAddress = Address ( _o [ " currentCoinbase " ] . get_str ( ) ) ;
}
mObject FakeExtVM : : exportState ( )
{
mObject ret ;
for ( auto const & a : addresses )
2014-02-21 19:18:30 +00:00
{
2014-09-27 10:51:34 +00:00
mObject o ;
push ( o , " balance " , get < 0 > ( a . second ) ) ;
push ( o , " nonce " , get < 1 > ( a . second ) ) ;
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
{
mObject store ;
for ( auto const & s : get < 2 > ( a . second ) )
2014-10-06 19:42:41 +00:00
store [ " 0x " + toHex ( toCompactBigEndian ( s . first ) ) ] = " 0x " + toHex ( toCompactBigEndian ( s . second ) ) ;
2014-09-27 10:51:34 +00:00
o [ " storage " ] = store ;
2014-02-21 19:18:30 +00:00
}
2014-09-27 10:51:34 +00:00
o [ " code " ] = " 0x " + toHex ( get < 3 > ( a . second ) ) ;
ret [ toString ( a . first ) ] = o ;
2014-02-21 19:18:30 +00:00
}
2014-09-27 10:51:34 +00:00
return ret ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : importState ( mObject & _object )
{
for ( auto const & i : _object )
2014-02-21 19:18:30 +00:00
{
2014-09-27 10:51:34 +00:00
mObject o = i . second . get_obj ( ) ;
2014-10-14 13:13:38 +00:00
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert ( o . count ( " balance " ) > 0 ) ;
assert ( o . count ( " nonce " ) > 0 ) ;
assert ( o . count ( " storage " ) > 0 ) ;
assert ( o . count ( " code " ) > 0 ) ;
2014-09-27 10:51:34 +00:00
auto & a = addresses [ Address ( i . first ) ] ;
get < 0 > ( a ) = toInt ( o [ " balance " ] ) ;
get < 1 > ( a ) = toInt ( o [ " nonce " ] ) ;
for ( auto const & j : o [ " storage " ] . get_obj ( ) )
2014-10-06 19:42:41 +00:00
get < 2 > ( a ) [ toInt ( j . first ) ] = toInt ( j . second ) ;
2014-07-06 14:16:53 +00:00
2014-11-03 15:33:02 +00:00
get < 3 > ( a ) = importCode ( o ) ;
2014-02-21 19:18:30 +00:00
}
2014-09-27 10:51:34 +00:00
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
mObject FakeExtVM : : exportExec ( )
{
mObject ret ;
ret [ " address " ] = toString ( myAddress ) ;
ret [ " caller " ] = toString ( caller ) ;
ret [ " origin " ] = toString ( origin ) ;
push ( ret , " value " , value ) ;
push ( ret , " gasPrice " , gasPrice ) ;
push ( ret , " gas " , gas ) ;
ret [ " data " ] = " 0x " + toHex ( data ) ;
ret [ " code " ] = " 0x " + toHex ( code ) ;
return ret ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : importExec ( mObject & _o )
{
2014-10-14 13:13:38 +00:00
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert ( _o . count ( " address " ) > 0 ) ;
assert ( _o . count ( " caller " ) > 0 ) ;
assert ( _o . count ( " origin " ) > 0 ) ;
assert ( _o . count ( " value " ) > 0 ) ;
assert ( _o . count ( " data " ) > 0 ) ;
assert ( _o . count ( " gasPrice " ) > 0 ) ;
assert ( _o . count ( " gas " ) > 0 ) ;
2014-09-27 10:51:34 +00:00
myAddress = Address ( _o [ " address " ] . get_str ( ) ) ;
caller = Address ( _o [ " caller " ] . get_str ( ) ) ;
origin = Address ( _o [ " origin " ] . get_str ( ) ) ;
value = toInt ( _o [ " value " ] ) ;
gasPrice = toInt ( _o [ " gasPrice " ] ) ;
gas = toInt ( _o [ " gas " ] ) ;
thisTxCode . clear ( ) ;
2014-11-03 22:49:05 +00:00
code = thisTxCode ;
2014-11-03 15:33:02 +00:00
thisTxCode = importCode ( _o ) ;
if ( _o [ " code " ] . type ( ) ! = str_type & & _o [ " code " ] . type ( ) ! = array_type )
2014-11-03 22:49:05 +00:00
code . clear ( ) ;
2014-09-27 10:51:34 +00:00
thisTxData . clear ( ) ;
2014-11-03 15:33:02 +00:00
thisTxData = importData ( _o ) ;
2014-09-27 10:51:34 +00:00
data = & thisTxData ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
mArray FakeExtVM : : exportCallCreates ( )
{
mArray ret ;
for ( Transaction const & tx : callcreates )
2014-02-21 19:18:30 +00:00
{
2014-09-27 10:51:34 +00:00
mObject o ;
2014-11-05 20:02:16 +00:00
o [ " destination " ] = tx . isCreation ( ) ? " " : toString ( tx . receiveAddress ( ) ) ;
2014-11-05 13:45:19 +00:00
push ( o , " gasLimit " , tx . gas ( ) ) ;
push ( o , " value " , tx . value ( ) ) ;
o [ " data " ] = " 0x " + toHex ( tx . data ( ) ) ;
2014-09-27 10:51:34 +00:00
ret . push_back ( o ) ;
2014-02-21 19:18:30 +00:00
}
2014-09-27 10:51:34 +00:00
return ret ;
}
2014-02-21 19:18:30 +00:00
2014-09-27 10:51:34 +00:00
void FakeExtVM : : importCallCreates ( mArray & _callcreates )
{
for ( mValue & v : _callcreates )
2014-02-21 19:18:30 +00:00
{
2014-09-27 10:51:34 +00:00
auto tx = v . get_obj ( ) ;
BOOST_REQUIRE ( tx . count ( " data " ) > 0 ) ;
BOOST_REQUIRE ( tx . count ( " value " ) > 0 ) ;
BOOST_REQUIRE ( tx . count ( " destination " ) > 0 ) ;
BOOST_REQUIRE ( tx . count ( " gasLimit " ) > 0 ) ;
2014-11-05 20:55:10 +00:00
Transaction t = tx [ " destination " ] . get_str ( ) . empty ( ) ?
2014-11-05 17:30:38 +00:00
Transaction ( toInt ( tx [ " value " ] ) , 0 , toInt ( tx [ " gasLimit " ] ) , data . toBytes ( ) ) :
Transaction ( toInt ( tx [ " value " ] ) , 0 , toInt ( tx [ " gasLimit " ] ) , Address ( tx [ " destination " ] . get_str ( ) ) , data . toBytes ( ) ) ;
2014-09-27 10:51:34 +00:00
callcreates . push_back ( t ) ;
2014-02-21 19:18:30 +00:00
}
2014-09-27 10:51:34 +00:00
}
2014-02-21 01:09:15 +00:00
2014-10-28 11:11:52 +00:00
eth : : OnOpFunc FakeExtVM : : simpleTrace ( )
{
2014-12-11 19:07:07 +00:00
return [ ] ( uint64_t steps , eth : : Instruction inst , bigint newMemSize , bigint gasCost , dev : : eth : : VM * voidVM , dev : : eth : : ExtVMFace const * voidExt )
2014-10-28 11:11:52 +00:00
{
2014-12-11 19:07:07 +00:00
FakeExtVM const & ext = * static_cast < FakeExtVM const * > ( voidExt ) ;
eth : : VM & vm = * voidVM ;
2014-10-28 11:11:52 +00:00
std : : ostringstream o ;
o < < std : : endl < < " STACK " < < std : : endl ;
for ( auto i : vm . stack ( ) )
o < < ( h256 ) i < < std : : endl ;
o < < " MEMORY " < < std : : endl < < memDump ( vm . memory ( ) ) ;
o < < " STORAGE " < < std : : endl ;
for ( auto const & i : std : : get < 2 > ( ext . addresses . find ( ext . myAddress ) - > second ) )
o < < std : : showbase < < std : : hex < < i . first < < " : " < < i . second < < std : : endl ;
dev : : LogOutputStream < eth : : VMTraceChannel , false > ( true ) < < o . str ( ) ;
dev : : LogOutputStream < eth : : VMTraceChannel , false > ( false ) < < " | " < < std : : dec < < ext . depth < < " | " < < ext . myAddress < < " | # " < < steps < < " | " < < std : : hex < < std : : setw ( 4 ) < < std : : setfill ( ' 0 ' ) < < vm . curPC ( ) < < " : " < < instructionInfo ( inst ) . name < < " | " < < std : : dec < < vm . gas ( ) < < " | - " < < std : : dec < < gasCost < < " | " < < newMemSize < < " x32 " < < " ] " ;
2014-12-12 14:35:18 +00:00
/*creates json stack trace*/
2014-10-28 11:11:52 +00:00
if ( eth : : VMTraceChannel : : verbosity < = g_logVerbosity )
{
2014-12-14 18:11:54 +00:00
Object o_step ;
2014-12-12 14:35:18 +00:00
2014-12-14 18:11:54 +00:00
/*add the stack*/
Array a_stack ;
for ( auto i : vm . stack ( ) )
a_stack . push_back ( ( string ) i ) ;
2014-12-12 14:35:18 +00:00
2014-12-14 18:11:54 +00:00
o_step . push_back ( Pair ( " stack " , a_stack ) ) ;
2014-12-12 14:35:18 +00:00
2014-12-14 18:11:54 +00:00
/*add the memory*/
Array a_mem ;
2014-12-12 14:35:18 +00:00
for ( auto i : vm . memory ( ) )
2014-12-14 18:11:54 +00:00
a_mem . push_back ( i ) ;
o_step . push_back ( Pair ( " memory " , a_mem ) ) ;
/*add the storage*/
Object storage ;
for ( auto const & i : std : : get < 2 > ( ext . addresses . find ( ext . myAddress ) - > second ) )
storage . push_back ( Pair ( ( string ) i . first , ( string ) i . second ) ) ;
/*add all the other details*/
o_step . push_back ( Pair ( " storage " , storage ) ) ;
o_step . push_back ( Pair ( " depth " , to_string ( ext . depth ) ) ) ;
o_step . push_back ( Pair ( " gas " , ( string ) vm . gas ( ) ) ) ;
o_step . push_back ( Pair ( " address " , " 0x " + toString ( ext . myAddress ) ) ) ;
o_step . push_back ( Pair ( " step " , steps ) ) ;
o_step . push_back ( Pair ( " pc " , ( int ) vm . curPC ( ) ) ) ;
o_step . push_back ( Pair ( " opcode " , instructionInfo ( inst ) . name ) ) ;
2014-12-16 19:28:03 +00:00
/*append the JSON object to the log file*/
Value v ( o_step ) ;
ofstream os ( " ./stackTrace.json " , ofstream : : app ) ;
os < < write_string ( v , true ) < < " , " ;
2014-12-14 18:11:54 +00:00
os . close ( ) ;
2014-10-28 11:11:52 +00:00
}
} ;
}
2014-09-27 10:51:34 +00:00
namespace dev { namespace test {
2014-02-17 21:07:09 +00:00
2014-11-03 15:33:02 +00:00
void doVMTests ( json_spirit : : mValue & v , bool _fillin )
2014-05-12 13:40:26 +00:00
{
2014-12-12 10:48:15 +00:00
processCommandLineOptions ( ) ;
2014-05-12 13:40:26 +00:00
for ( auto & i : v . get_obj ( ) )
2014-02-21 19:18:30 +00:00
{
2014-05-12 13:40:26 +00:00
cnote < < i . first ;
mObject & o = i . second . get_obj ( ) ;
2014-02-21 19:18:30 +00:00
2014-05-12 13:40:26 +00:00
BOOST_REQUIRE ( o . count ( " env " ) > 0 ) ;
BOOST_REQUIRE ( o . count ( " pre " ) > 0 ) ;
BOOST_REQUIRE ( o . count ( " exec " ) > 0 ) ;
2014-04-20 05:09:41 +00:00
2014-12-12 10:48:15 +00:00
FakeExtVM fev ;
2014-05-12 13:40:26 +00:00
fev . importEnv ( o [ " env " ] . get_obj ( ) ) ;
fev . importState ( o [ " pre " ] . get_obj ( ) ) ;
2014-02-21 19:18:30 +00:00
2014-05-12 13:40:26 +00:00
if ( _fillin )
o [ " pre " ] = mValue ( fev . exportState ( ) ) ;
2014-02-21 19:18:30 +00:00
2014-06-27 19:39:46 +00:00
fev . importExec ( o [ " exec " ] . get_obj ( ) ) ;
2014-11-07 14:16:42 +00:00
if ( fev . code . empty ( ) )
2014-07-10 09:16:34 +00:00
{
fev . thisTxCode = get < 3 > ( fev . addresses . at ( fev . myAddress ) ) ;
2014-11-03 22:49:05 +00:00
fev . code = fev . thisTxCode ;
2014-07-10 09:16:34 +00:00
}
2014-10-01 11:59:07 +00:00
2014-09-25 09:18:32 +00:00
bytes output ;
2014-11-10 21:26:07 +00:00
u256 gas ;
2014-11-19 12:13:19 +00:00
bool vmExceptionOccured = false ;
2014-12-10 22:42:01 +00:00
auto startTime = std : : chrono : : high_resolution_clock : : now ( ) ;
2014-09-25 09:18:32 +00:00
try
{
2014-12-10 22:42:01 +00:00
auto vm = eth : : VMFactory : : create ( fev . gas ) ;
2014-11-26 19:20:52 +00:00
output = vm - > go ( fev , fev . simpleTrace ( ) ) . toBytes ( ) ;
2014-11-14 10:07:14 +00:00
gas = vm - > gas ( ) ;
2014-10-21 12:44:09 +00:00
}
2014-11-10 21:26:07 +00:00
catch ( VMException const & _e )
{
2014-12-12 21:16:51 +00:00
cnote < < " Safe VM Exception " ;
2014-11-19 12:13:19 +00:00
vmExceptionOccured = true ;
2014-09-25 09:18:32 +00:00
}
2014-10-02 12:20:33 +00:00
catch ( Exception const & _e )
2014-09-25 09:18:32 +00:00
{
2014-10-02 12:20:33 +00:00
cnote < < " VM did throw an exception: " < < diagnostic_information ( _e ) ;
2014-11-10 21:26:07 +00:00
BOOST_ERROR ( " Failed VM Test with Exception: " < < _e . what ( ) ) ;
2014-10-02 12:20:33 +00:00
}
catch ( std : : exception const & _e )
{
cnote < < " VM did throw an exception: " < < _e . what ( ) ;
2014-11-10 21:26:07 +00:00
BOOST_ERROR ( " Failed VM Test with Exception: " < < _e . what ( ) ) ;
2014-09-25 09:18:32 +00:00
}
2014-10-29 10:29:34 +00:00
auto endTime = std : : chrono : : high_resolution_clock : : now ( ) ;
2014-12-12 10:48:15 +00:00
auto argc = boost : : unit_test : : framework : : master_test_suite ( ) . argc ;
auto argv = boost : : unit_test : : framework : : master_test_suite ( ) . argv ;
2014-10-29 11:02:37 +00:00
for ( auto i = 0 ; i < argc ; + + i )
{
if ( std : : string ( argv [ i ] ) = = " --show-times " )
{
auto testDuration = endTime - startTime ;
cnote < < " Execution time: "
< < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( testDuration ) . count ( )
< < " ms " ;
2014-10-31 14:47:16 +00:00
break ;
2014-10-29 11:02:37 +00:00
}
2014-10-29 10:29:34 +00:00
}
2014-09-27 10:51:34 +00:00
// delete null entries in storage for the sake of comparison
for ( auto & a : fev . addresses )
{
vector < u256 > keystoDelete ;
for ( auto & s : get < 2 > ( a . second ) )
{
if ( s . second = = 0 )
keystoDelete . push_back ( s . first ) ;
}
for ( auto const key : keystoDelete )
{
get < 2 > ( a . second ) . erase ( key ) ;
}
}
2014-05-12 13:40:26 +00:00
if ( _fillin )
{
2014-07-10 10:29:39 +00:00
o [ " env " ] = mValue ( fev . exportEnv ( ) ) ;
2014-06-27 19:39:46 +00:00
o [ " exec " ] = mValue ( fev . exportExec ( ) ) ;
2014-11-19 12:13:19 +00:00
if ( ! vmExceptionOccured )
{
2014-11-20 19:13:28 +00:00
o [ " post " ] = mValue ( fev . exportState ( ) ) ;
o [ " callcreates " ] = fev . exportCallCreates ( ) ;
o [ " out " ] = " 0x " + toHex ( output ) ;
fev . push ( o , " gas " , gas ) ;
2014-12-05 18:26:32 +00:00
o [ " logs " ] = exportLog ( fev . sub . logs ) ;
2014-11-20 19:13:28 +00:00
}
2014-05-12 13:40:26 +00:00
}
else
{
2014-11-19 12:13:19 +00:00
if ( o . count ( " post " ) > 0 ) // No exceptions expected
{
BOOST_CHECK ( ! vmExceptionOccured ) ;
2014-05-12 13:40:26 +00:00
2014-11-19 12:13:19 +00:00
BOOST_REQUIRE ( o . count ( " post " ) > 0 ) ;
BOOST_REQUIRE ( o . count ( " callcreates " ) > 0 ) ;
BOOST_REQUIRE ( o . count ( " out " ) > 0 ) ;
BOOST_REQUIRE ( o . count ( " gas " ) > 0 ) ;
2014-11-20 15:59:27 +00:00
BOOST_REQUIRE ( o . count ( " logs " ) > 0 ) ;
2014-05-12 13:40:26 +00:00
2014-11-19 12:13:19 +00:00
dev : : test : : FakeExtVM test ;
test . importState ( o [ " post " ] . get_obj ( ) ) ;
test . importCallCreates ( o [ " callcreates " ] . get_array ( ) ) ;
2014-12-05 18:26:32 +00:00
test . sub . logs = importLog ( o [ " logs " ] . get_array ( ) ) ;
2014-07-14 15:24:07 +00:00
2014-12-19 13:38:03 +00:00
checkOutput ( output , o ) ;
2014-11-03 15:33:02 +00:00
2014-12-19 13:38:03 +00:00
BOOST_CHECK_EQUAL ( toInt ( o [ " gas " ] ) , gas ) ;
2014-10-21 09:54:54 +00:00
2014-12-19 13:38:03 +00:00
auto & expectedAddrs = test . addresses ;
auto & resultAddrs = fev . addresses ;
for ( auto & & expectedPair : expectedAddrs )
{
auto & expectedAddr = expectedPair . first ;
auto resultAddrIt = resultAddrs . find ( expectedAddr ) ;
if ( resultAddrIt = = resultAddrs . end ( ) )
BOOST_ERROR ( " Missing expected address " < < expectedAddr ) ;
else
{
auto & expectedState = expectedPair . second ;
auto & resultState = resultAddrIt - > second ;
BOOST_CHECK_MESSAGE ( std : : get < 0 > ( expectedState ) = = std : : get < 0 > ( resultState ) , expectedAddr < < " : incorrect balance " < < std : : get < 0 > ( resultState ) < < " , expected " < < std : : get < 0 > ( expectedState ) ) ;
BOOST_CHECK_MESSAGE ( std : : get < 1 > ( expectedState ) = = std : : get < 1 > ( resultState ) , expectedAddr < < " : incorrect txCount " < < std : : get < 1 > ( resultState ) < < " , expected " < < std : : get < 1 > ( expectedState ) ) ;
BOOST_CHECK_MESSAGE ( std : : get < 3 > ( expectedState ) = = std : : get < 3 > ( resultState ) , expectedAddr < < " : incorrect code " ) ;
checkStorage ( std : : get < 2 > ( expectedState ) , std : : get < 2 > ( resultState ) , expectedAddr ) ;
}
2014-10-21 09:54:54 +00:00
}
2014-11-19 12:13:19 +00:00
checkAddresses < std : : map < Address , std : : tuple < u256 , u256 , std : : map < u256 , u256 > , bytes > > > ( test . addresses , fev . addresses ) ;
BOOST_CHECK ( test . callcreates = = fev . callcreates ) ;
2014-11-19 13:30:42 +00:00
2014-11-20 15:59:27 +00:00
checkLog ( fev . sub . logs , test . sub . logs ) ;
2014-11-19 12:13:19 +00:00
}
else // Exception expected
BOOST_CHECK ( vmExceptionOccured ) ;
2014-02-21 19:18:30 +00:00
}
}
2014-05-12 13:40:26 +00:00
}
2014-09-25 09:18:32 +00:00
} } // Namespace Close
2014-11-03 15:33:02 +00:00
BOOST_AUTO_TEST_SUITE ( VMTests )
2014-09-25 09:18:32 +00:00
BOOST_AUTO_TEST_CASE ( vm_tests )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmtests " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-04-19 17:55:20 +00:00
}
2014-09-20 00:05:04 +00:00
BOOST_AUTO_TEST_CASE ( vmArithmeticTest )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmArithmeticTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-25 09:18:32 +00:00
}
2014-09-20 00:05:04 +00:00
2014-09-25 09:18:32 +00:00
BOOST_AUTO_TEST_CASE ( vmBitwiseLogicOperationTest )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmBitwiseLogicOperationTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-25 09:18:32 +00:00
}
BOOST_AUTO_TEST_CASE ( vmSha3Test )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmSha3Test " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-20 00:05:04 +00:00
}
2014-09-25 09:18:32 +00:00
BOOST_AUTO_TEST_CASE ( vmEnvironmentalInfoTest )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmEnvironmentalInfoTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-25 09:18:32 +00:00
}
BOOST_AUTO_TEST_CASE ( vmBlockInfoTest )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmBlockInfoTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-25 09:18:32 +00:00
}
BOOST_AUTO_TEST_CASE ( vmIOandFlowOperationsTest )
{
2014-11-04 23:12:29 +00:00
dev : : test : : executeTests ( " vmIOandFlowOperationsTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-25 09:18:32 +00:00
}
BOOST_AUTO_TEST_CASE ( vmPushDupSwapTest )
{
2014-11-03 15:33:02 +00:00
dev : : test : : executeTests ( " vmPushDupSwapTest " , " /VMTests " , dev : : test : : doVMTests ) ;
2014-09-27 10:51:34 +00:00
}
2014-10-06 19:42:41 +00:00
2014-11-19 13:30:42 +00:00
BOOST_AUTO_TEST_CASE ( vmLogTest )
{
dev : : test : : executeTests ( " vmLogTest " , " /VMTests " , dev : : test : : doVMTests ) ;
}
2014-12-04 16:55:04 +00:00
BOOST_AUTO_TEST_CASE ( vmPerformanceTest )
{
for ( int i = 1 ; i < boost : : unit_test : : framework : : master_test_suite ( ) . argc ; + + i )
{
string arg = boost : : unit_test : : framework : : master_test_suite ( ) . argv [ i ] ;
if ( arg = = " --performance " )
dev : : test : : executeTests ( " vmPerformanceTest " , " /VMTests " , dev : : test : : doVMTests ) ;
}
}
BOOST_AUTO_TEST_CASE ( vmArithPerformanceTest )
{
for ( int i = 1 ; i < boost : : unit_test : : framework : : master_test_suite ( ) . argc ; + + i )
{
string arg = boost : : unit_test : : framework : : master_test_suite ( ) . argv [ i ] ;
if ( arg = = " --performance " )
dev : : test : : executeTests ( " vmArithPerformanceTest " , " /VMTests " , dev : : test : : doVMTests ) ;
}
}
2014-11-07 12:29:13 +00:00
BOOST_AUTO_TEST_CASE ( vmRandom )
2014-10-27 17:59:42 +00:00
{
2014-11-07 12:29:13 +00:00
string testPath = getTestPath ( ) ;
testPath + = " /VMTests/RandomTests " ;
vector < boost : : filesystem : : path > testFiles ;
boost : : filesystem : : directory_iterator iterator ( testPath ) ;
for ( ; iterator ! = boost : : filesystem : : directory_iterator ( ) ; + + iterator )
if ( boost : : filesystem : : is_regular_file ( iterator - > path ( ) ) & & iterator - > path ( ) . extension ( ) = = " .json " )
testFiles . push_back ( iterator - > path ( ) ) ;
for ( auto & path : testFiles )
2014-10-27 17:59:42 +00:00
{
try
{
2014-11-07 12:29:13 +00:00
cnote < < " Testing ... " < < path . filename ( ) ;
2014-10-27 17:59:42 +00:00
json_spirit : : mValue v ;
2014-11-10 16:37:55 +00:00
string s = asString ( dev : : contents ( path . string ( ) ) ) ;
BOOST_REQUIRE_MESSAGE ( s . length ( ) > 0 , " Content of " + path . string ( ) + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path? " ) ;
2014-10-27 17:59:42 +00:00
json_spirit : : read_string ( s , v ) ;
2014-11-07 12:29:13 +00:00
doVMTests ( v , false ) ;
2014-10-27 17:59:42 +00:00
}
catch ( Exception const & _e )
{
2014-11-07 12:29:13 +00:00
BOOST_ERROR ( " Failed test with Exception: " < < diagnostic_information ( _e ) ) ;
2014-10-27 17:59:42 +00:00
}
catch ( std : : exception const & _e )
{
2014-11-07 12:29:13 +00:00
BOOST_ERROR ( " Failed test with Exception: " < < _e . what ( ) ) ;
2014-10-27 17:59:42 +00:00
}
}
}
2014-11-03 15:33:02 +00:00
2014-11-10 06:12:29 +00:00
BOOST_AUTO_TEST_CASE ( userDefinedFileVM )
2014-10-27 17:59:42 +00:00
{
2014-11-10 17:30:35 +00:00
dev : : test : : userDefinedTest ( " --vmtest " , dev : : test : : doVMTests ) ;
2014-10-27 17:59:42 +00:00
}
2014-11-03 15:33:02 +00:00
BOOST_AUTO_TEST_SUITE_END ( )