mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			260 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
	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/>.
 | 
						|
*/
 | 
						|
/** @file state.cpp
 | 
						|
 * @author Christoph Jentzsch <cj@ethdev.com>
 | 
						|
 * @date 2014
 | 
						|
 * State test functions.
 | 
						|
 */
 | 
						|
 | 
						|
#include <boost/filesystem/operations.hpp>
 | 
						|
#include <boost/test/unit_test.hpp>
 | 
						|
 | 
						|
#include "JsonSpiritHeaders.h"
 | 
						|
#include <libdevcore/CommonIO.h>
 | 
						|
#include <libethereum/CanonBlockChain.h>
 | 
						|
#include <libethereum/State.h>
 | 
						|
#include <libethereum/ExtVM.h>
 | 
						|
#include <libethereum/Defaults.h>
 | 
						|
#include <libevm/VM.h>
 | 
						|
#include "TestHelper.h"
 | 
						|
 | 
						|
using namespace std;
 | 
						|
using namespace json_spirit;
 | 
						|
using namespace dev;
 | 
						|
using namespace dev::eth;
 | 
						|
 | 
						|
namespace dev {  namespace test {
 | 
						|
 | 
						|
void doStateTests(json_spirit::mValue& v, bool _fillin)
 | 
						|
{
 | 
						|
	processCommandLineOptions();
 | 
						|
 | 
						|
	for (auto& i: v.get_obj())
 | 
						|
	{
 | 
						|
		cerr << i.first << endl;
 | 
						|
		mObject& o = i.second.get_obj();
 | 
						|
 | 
						|
		BOOST_REQUIRE(o.count("env") > 0);
 | 
						|
		BOOST_REQUIRE(o.count("pre") > 0);
 | 
						|
		BOOST_REQUIRE(o.count("transaction") > 0);
 | 
						|
 | 
						|
		ImportTest importer(o, _fillin);
 | 
						|
 | 
						|
		State theState = importer.m_statePre;
 | 
						|
		bytes tx = importer.m_transaction.rlp();
 | 
						|
		bytes output;
 | 
						|
 | 
						|
		try
 | 
						|
		{
 | 
						|
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
 | 
						|
		}
 | 
						|
		catch (Exception const& _e)
 | 
						|
		{
 | 
						|
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
 | 
						|
			theState.commit();
 | 
						|
		}
 | 
						|
		catch (std::exception const& _e)
 | 
						|
		{
 | 
						|
			cnote << "state execution did throw an exception: " << _e.what();
 | 
						|
		}
 | 
						|
 | 
						|
		if (_fillin)
 | 
						|
		{
 | 
						|
#if ETH_FATDB
 | 
						|
			importer.exportTest(output, theState);
 | 
						|
#else
 | 
						|
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
 | 
						|
#endif
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			BOOST_REQUIRE(o.count("post") > 0);
 | 
						|
			BOOST_REQUIRE(o.count("out") > 0);
 | 
						|
 | 
						|
			// check output
 | 
						|
			checkOutput(output, o);
 | 
						|
 | 
						|
			// check logs
 | 
						|
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);
 | 
						|
 | 
						|
			// check addresses
 | 
						|
#if ETH_FATDB
 | 
						|
			auto expectedAddrs = importer.m_statePost.addresses();
 | 
						|
			auto resultAddrs = theState.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
 | 
						|
				{
 | 
						|
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
 | 
						|
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
 | 
						|
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");
 | 
						|
 | 
						|
					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
 | 
						|
				}
 | 
						|
			}
 | 
						|
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
 | 
						|
#endif
 | 
						|
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
} }// Namespace Close
 | 
						|
 | 
						|
BOOST_AUTO_TEST_SUITE(StateTests)
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stExample)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stLogTests)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stRecursiveCreate)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stInitCodeTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stTransactionTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stSpecialTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stRefundTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stBlockHashTest)
 | 
						|
{
 | 
						|
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
 | 
						|
{
 | 
						|
	   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 == "--quadratic" || arg == "--all")
 | 
						|
			   {
 | 
						|
					   auto start = chrono::steady_clock::now();
 | 
						|
 | 
						|
					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);
 | 
						|
 | 
						|
					   auto end = chrono::steady_clock::now();
 | 
						|
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
 | 
						|
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
 | 
						|
			   }
 | 
						|
	   }
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stMemoryStressTest)
 | 
						|
{
 | 
						|
	   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 == "--memory" || arg == "--all")
 | 
						|
			   {
 | 
						|
					   auto start = chrono::steady_clock::now();
 | 
						|
 | 
						|
					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);
 | 
						|
 | 
						|
					   auto end = chrono::steady_clock::now();
 | 
						|
					   auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
 | 
						|
					   cnote << "test duration: " << duration.count() << " milliseconds.\n";
 | 
						|
			   }
 | 
						|
	   }
 | 
						|
}
 | 
						|
 | 
						|
 BOOST_AUTO_TEST_CASE(stSolidityTest)
 | 
						|
 {
 | 
						|
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 | 
						|
 }
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stMemoryTest)
 | 
						|
{
 | 
						|
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(stCreateTest)
 | 
						|
{
 | 
						|
	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 == "--createtest")
 | 
						|
		{
 | 
						|
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
 | 
						|
			{
 | 
						|
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			try
 | 
						|
			{
 | 
						|
				cnote << "Populating tests...";
 | 
						|
				json_spirit::mValue v;
 | 
						|
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
 | 
						|
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
 | 
						|
				json_spirit::read_string(s, v);
 | 
						|
				dev::test::doStateTests(v, true);
 | 
						|
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
 | 
						|
			}
 | 
						|
			catch (Exception const& _e)
 | 
						|
			{
 | 
						|
				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
 | 
						|
			}
 | 
						|
			catch (std::exception const& _e)
 | 
						|
			{
 | 
						|
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_CASE(userDefinedFileState)
 | 
						|
{
 | 
						|
	dev::test::userDefinedTest("--singletest", dev::test::doStateTests);
 | 
						|
}
 | 
						|
 | 
						|
BOOST_AUTO_TEST_SUITE_END()
 |