mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/develop' into evmjit-develop
Conflicts: evmjit/CMakeLists.txt evmjit/libevmjit/Arith256.cpp
This commit is contained in:
		
						commit
						79e7325e3f
					
				| @ -230,7 +230,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state) | ||||
| 	{ | ||||
| 		//check that every parameter was declared in state object
 | ||||
| 		if (!stateOptionMap.second.isAllSet()) | ||||
| 			BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));	 | ||||
| 			BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!")); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -285,9 +285,9 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta | ||||
| 	#define CHECK(a,b)						\ | ||||
| 		{									\ | ||||
| 			if (_throw == WhenError::Throw) \ | ||||
| 				BOOST_CHECK_MESSAGE(a,b);	\ | ||||
| 				{TBOOST_CHECK_MESSAGE(a,b);}\ | ||||
| 			else							\ | ||||
| 				BOOST_WARN_MESSAGE(a,b);	\ | ||||
| 				{TBOOST_WARN_MESSAGE(a,b);}	\ | ||||
| 		} | ||||
| 
 | ||||
| 	for (auto const& a: _stateExpect.addresses()) | ||||
| @ -304,35 +304,35 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta | ||||
| 				} | ||||
| 				catch(std::out_of_range const&) | ||||
| 				{ | ||||
| 					BOOST_ERROR("expectedStateOptions map does not match expectedState in checkExpectedState!"); | ||||
| 					TBOOST_ERROR("expectedStateOptions map does not match expectedState in checkExpectedState!"); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (addressOptions.m_bHasBalance) | ||||
| 				CHECK(_stateExpect.balance(a.first) == _statePost.balance(a.first), | ||||
| 				CHECK((_stateExpect.balance(a.first) == _statePost.balance(a.first)), | ||||
| 						"Check State: " << a.first <<  ": incorrect balance " << _statePost.balance(a.first) << ", expected " << _stateExpect.balance(a.first)); | ||||
| 
 | ||||
| 			if (addressOptions.m_bHasNonce) | ||||
| 				CHECK(_stateExpect.transactionsFrom(a.first) == _statePost.transactionsFrom(a.first), | ||||
| 				CHECK((_stateExpect.transactionsFrom(a.first) == _statePost.transactionsFrom(a.first)), | ||||
| 						"Check State: " << a.first <<  ": incorrect nonce " << _statePost.transactionsFrom(a.first) << ", expected " << _stateExpect.transactionsFrom(a.first)); | ||||
| 
 | ||||
| 			if (addressOptions.m_bHasStorage) | ||||
| 			{ | ||||
| 				unordered_map<u256, u256> stateStorage = _statePost.storage(a.first); | ||||
| 				for (auto const& s: _stateExpect.storage(a.first)) | ||||
| 					CHECK(stateStorage[s.first] == s.second, | ||||
| 					CHECK((stateStorage[s.first] == s.second), | ||||
| 							"Check State: " << a.first <<  ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second)); | ||||
| 
 | ||||
| 				//Check for unexpected storage values
 | ||||
| 				stateStorage = _stateExpect.storage(a.first); | ||||
| 				for (auto const& s: _statePost.storage(a.first)) | ||||
| 					CHECK(stateStorage[s.first] == s.second, | ||||
| 					CHECK((stateStorage[s.first] == s.second), | ||||
| 							"Check State: " << a.first <<  ": incorrect storage [" << s.first << "] = " << toHex(s.second) << ", expected [" << s.first << "] = " << toHex(stateStorage[s.first])); | ||||
| 			} | ||||
| 
 | ||||
| 			if (addressOptions.m_bHasCode) | ||||
| 				CHECK(_stateExpect.code(a.first) == _statePost.code(a.first), | ||||
| 				CHECK((_stateExpect.code(a.first) == _statePost.code(a.first)), | ||||
| 						"Check State: " << a.first <<  ": incorrect code '" << toHex(_statePost.code(a.first)) << "', expected '" << toHex(_stateExpect.code(a.first)) << "'"); | ||||
| 		} | ||||
| 	} | ||||
| @ -349,9 +349,9 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost) | ||||
| 	{ | ||||
| 		std::string warning = "Check State: Error! Unexpected output: " + m_TestObject["out"].get_str() + " Expected: " + m_TestObject["expectOut"].get_str(); | ||||
| 		if (Options::get().checkState) | ||||
| 			BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); | ||||
| 			{TBOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);} | ||||
| 		else | ||||
| 			BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); | ||||
| 			TBOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); | ||||
| 
 | ||||
| 		m_TestObject.erase(m_TestObject.find("expectOut")); | ||||
| 	} | ||||
| @ -518,65 +518,65 @@ void checkOutput(bytes const& _output, json_spirit::mObject& _o) | ||||
| 	int j = 0; | ||||
| 
 | ||||
| 	if (_o["out"].get_str().find("#") == 0) | ||||
| 		BOOST_CHECK((u256)_output.size() == toInt(_o["out"].get_str().substr(1))); | ||||
| 
 | ||||
| 		{TBOOST_CHECK(((u256)_output.size() == toInt(_o["out"].get_str().substr(1))));} | ||||
| 	else if (_o["out"].type() == json_spirit::array_type) | ||||
| 		for (auto const& d: _o["out"].get_array()) | ||||
| 		{ | ||||
| 			BOOST_CHECK_MESSAGE(_output[j] == toInt(d), "Output byte [" << j << "] different!"); | ||||
| 			TBOOST_CHECK_MESSAGE((_output[j] == toInt(d)), "Output byte [" << j << "] different!"); | ||||
| 			++j; | ||||
| 		} | ||||
| 	else if (_o["out"].get_str().find("0x") == 0) | ||||
| 		BOOST_CHECK(_output == fromHex(_o["out"].get_str().substr(2))); | ||||
| 		{TBOOST_CHECK((_output == fromHex(_o["out"].get_str().substr(2))));} | ||||
| 	else | ||||
| 		BOOST_CHECK(_output == fromHex(_o["out"].get_str())); | ||||
| 		TBOOST_CHECK((_output == fromHex(_o["out"].get_str()))); | ||||
| } | ||||
| 
 | ||||
| void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, Address _expectedAddr) | ||||
| { | ||||
| 	_expectedAddr = _expectedAddr; //unsed parametr when macro
 | ||||
| 	for (auto&& expectedStorePair : _expectedStore) | ||||
| 	{ | ||||
| 		auto& expectedStoreKey = expectedStorePair.first; | ||||
| 		auto resultStoreIt = _resultStore.find(expectedStoreKey); | ||||
| 		if (resultStoreIt == _resultStore.end()) | ||||
| 			BOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey); | ||||
| 			{TBOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey);} | ||||
| 		else | ||||
| 		{ | ||||
| 			auto& expectedStoreValue = expectedStorePair.second; | ||||
| 			auto& resultStoreValue = resultStoreIt->second; | ||||
| 			BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); | ||||
| 			TBOOST_CHECK_MESSAGE((expectedStoreValue == resultStoreValue), _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); | ||||
| 		} | ||||
| 	} | ||||
| 	BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); | ||||
| 	TBOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); | ||||
| 	for (auto&& resultStorePair: _resultStore) | ||||
| 	{ | ||||
| 		if (!_expectedStore.count(resultStorePair.first)) | ||||
| 			BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); | ||||
| 			TBOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) | ||||
| { | ||||
| 	BOOST_REQUIRE_EQUAL(_resultLogs.size(), _expectedLogs.size()); | ||||
| 	TBOOST_REQUIRE_EQUAL(_resultLogs.size(), _expectedLogs.size()); | ||||
| 
 | ||||
| 	for (size_t i = 0; i < _resultLogs.size(); ++i) | ||||
| 	{ | ||||
| 		BOOST_CHECK_EQUAL(_resultLogs[i].address, _expectedLogs[i].address); | ||||
| 		BOOST_CHECK_EQUAL(_resultLogs[i].topics, _expectedLogs[i].topics); | ||||
| 		BOOST_CHECK(_resultLogs[i].data == _expectedLogs[i].data); | ||||
| 		TBOOST_CHECK_EQUAL(_resultLogs[i].address, _expectedLogs[i].address); | ||||
| 		TBOOST_CHECK_EQUAL(_resultLogs[i].topics, _expectedLogs[i].topics); | ||||
| 		TBOOST_CHECK((_resultLogs[i].data == _expectedLogs[i].data)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates) | ||||
| { | ||||
| 	BOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size()); | ||||
| 	TBOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size()); | ||||
| 
 | ||||
| 	for (size_t i = 0; i < _resultCallCreates.size(); ++i) | ||||
| 	{ | ||||
| 		BOOST_CHECK(_resultCallCreates[i].data() == _expectedCallCreates[i].data()); | ||||
| 		BOOST_CHECK(_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress()); | ||||
| 		BOOST_CHECK(_resultCallCreates[i].gas() == _expectedCallCreates[i].gas()); | ||||
| 		BOOST_CHECK(_resultCallCreates[i].value() == _expectedCallCreates[i].value()); | ||||
| 		TBOOST_CHECK((_resultCallCreates[i].data() == _expectedCallCreates[i].data())); | ||||
| 		TBOOST_CHECK((_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress())); | ||||
| 		TBOOST_CHECK((_resultCallCreates[i].gas() == _expectedCallCreates[i].gas())); | ||||
| 		TBOOST_CHECK((_resultCallCreates[i].value() == _expectedCallCreates[i].value())); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -598,8 +598,8 @@ void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests) | ||||
| 	{ | ||||
| 		cnote << "Testing user defined test: " << filename; | ||||
| 		json_spirit::mValue v; | ||||
| 		string s = asString(contents(filename)); | ||||
| 		BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); | ||||
| 		string s = contentsString(filename); | ||||
| 		TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + filename + " is empty. "); | ||||
| 		json_spirit::read_string(s, v); | ||||
| 		json_spirit::mObject oSingleTest; | ||||
| 
 | ||||
| @ -617,11 +617,11 @@ void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests) | ||||
| 	} | ||||
| 	catch (Exception const& _e) | ||||
| 	{ | ||||
| 		BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); | ||||
| 		TBOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); | ||||
| 	} | ||||
| 	catch (std::exception const& _e) | ||||
| 	{ | ||||
| 		BOOST_ERROR("Failed Test with Exception: " << _e.what()); | ||||
| 		TBOOST_ERROR("Failed Test with Exception: " << _e.what()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -641,18 +641,18 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo | ||||
| 			json_spirit::mValue v; | ||||
| 			boost::filesystem::path p(__FILE__); | ||||
| 			string s = asString(dev::contents(_pathToFiller.string() + "/" + _name + "Filler.json")); | ||||
| 			BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty."); | ||||
| 			TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty."); | ||||
| 			json_spirit::read_string(s, v); | ||||
| 			doTests(v, true); | ||||
| 			writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); | ||||
| 		} | ||||
| 		catch (Exception const& _e) | ||||
| 		{ | ||||
| 			BOOST_ERROR("Failed filling test with Exception: " << diagnostic_information(_e)); | ||||
| 			TBOOST_ERROR("Failed filling test with Exception: " << diagnostic_information(_e)); | ||||
| 		} | ||||
| 		catch (std::exception const& _e) | ||||
| 		{ | ||||
| 			BOOST_ERROR("Failed filling test with Exception: " << _e.what()); | ||||
| 			TBOOST_ERROR("Failed filling test with Exception: " << _e.what()); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -661,18 +661,18 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo | ||||
| 		std::cout << "TEST " << _name << ":\n"; | ||||
| 		json_spirit::mValue v; | ||||
| 		string s = asString(dev::contents(testPath + "/" + _name + ".json")); | ||||
| 		BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); | ||||
| 		TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); | ||||
| 		json_spirit::read_string(s, v); | ||||
| 		Listener::notifySuiteStarted(_name); | ||||
| 		doTests(v, false); | ||||
| 	} | ||||
| 	catch (Exception const& _e) | ||||
| 	{ | ||||
| 		BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); | ||||
| 		TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); | ||||
| 	} | ||||
| 	catch (std::exception const& _e) | ||||
| 	{ | ||||
| 		BOOST_ERROR("Failed test with Exception: " << _e.what()); | ||||
| 		TBOOST_ERROR("Failed test with Exception: " << _e.what()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -755,6 +755,10 @@ Options::Options() | ||||
| 			checkState = true; | ||||
| 		else if (arg == "--wallet") | ||||
| 			wallet = true; | ||||
| 		else if (arg == "--nonetwork") | ||||
| 			nonetwork = true; | ||||
| 		else if (arg == "--nodag") | ||||
| 			nodag = true; | ||||
| 		else if (arg == "--all") | ||||
| 		{ | ||||
| 			performance = true; | ||||
| @ -762,7 +766,7 @@ Options::Options() | ||||
| 			memory = true; | ||||
| 			inputLimits = true; | ||||
| 			bigData = true; | ||||
| 			wallet= true; | ||||
| 			wallet = true; | ||||
| 		} | ||||
| 		else if (arg == "--singletest" && i + 1 < argc) | ||||
| 		{ | ||||
|  | ||||
							
								
								
									
										32
									
								
								TestHelper.h
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								TestHelper.h
									
									
									
									
									
								
							| @ -31,6 +31,26 @@ | ||||
| #include <libevm/ExtVMFace.h> | ||||
| #include <libtestutils/Common.h> | ||||
| 
 | ||||
| #ifdef NOBOOST | ||||
| 	#define TBOOST_REQUIRE(arg) if(arg == false) throw dev::Exception(); | ||||
| 	#define TBOOST_REQUIRE_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception(); | ||||
| 	#define TBOOST_CHECK_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception(); | ||||
| 	#define TBOOST_CHECK(arg) if(arg == false) throw dev::Exception(); | ||||
| 	#define TBOOST_REQUIRE_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception(); | ||||
| 	#define TBOOST_CHECK_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception(); | ||||
| 	#define TBOOST_WARN_MESSAGE(arg1, arg2) throw dev::Exception(); | ||||
| 	#define TBOOST_ERROR(arg) throw dev::Exception(); | ||||
| #else | ||||
| 	#define TBOOST_REQUIRE(arg) BOOST_REQUIRE(arg) | ||||
| 	#define TBOOST_REQUIRE_EQUAL(arg1, arg2) BOOST_REQUIRE_EQUAL(arg1, arg2) | ||||
| 	#define TBOOST_CHECK(arg) BOOST_CHECK(arg) | ||||
| 	#define TBOOST_CHECK_EQUAL(arg1, arg2) BOOST_CHECK_EQUAL(arg1, arg2) | ||||
| 	#define TBOOST_CHECK_MESSAGE(arg1, arg2) BOOST_CHECK_MESSAGE(arg1, arg2) | ||||
| 	#define TBOOST_REQUIRE_MESSAGE(arg1, arg2) BOOST_REQUIRE_MESSAGE(arg1, arg2) | ||||
| 	#define TBOOST_WARN_MESSAGE(arg1, arg2) BOOST_WARN_MESSAGE(arg1, arg2) | ||||
| 	#define TBOOST_ERROR(arg) BOOST_ERROR(arg) | ||||
| #endif | ||||
| 
 | ||||
| namespace dev | ||||
| { | ||||
| namespace eth | ||||
| @ -163,6 +183,12 @@ eth::LastHashes lastHashes(u256 _currentBlockNumber); | ||||
| json_spirit::mObject fillJsonWithState(eth::State _state); | ||||
| json_spirit::mObject fillJsonWithTransaction(eth::Transaction _txn); | ||||
| 
 | ||||
| //Fill Test Functions
 | ||||
| void doTransactionTests(json_spirit::mValue& _v, bool _fillin); | ||||
| void doStateTests(json_spirit::mValue& v, bool _fillin); | ||||
| void doVMTests(json_spirit::mValue& v, bool _fillin); | ||||
| void doBlockchainTests(json_spirit::mValue& _v, bool _fillin); | ||||
| 
 | ||||
| template<typename mapType> | ||||
| void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) | ||||
| { | ||||
| @ -171,9 +197,9 @@ void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) | ||||
| 		auto& resultAddr = resultPair.first; | ||||
| 		auto expectedAddrIt = _expectedAddrs.find(resultAddr); | ||||
| 		if (expectedAddrIt == _expectedAddrs.end()) | ||||
| 			BOOST_ERROR("Missing result address " << resultAddr); | ||||
| 			TBOOST_ERROR("Missing result address " << resultAddr); | ||||
| 	} | ||||
| 	BOOST_CHECK(_expectedAddrs == _resultAddrs); | ||||
| 	TBOOST_CHECK((_expectedAddrs == _resultAddrs)); | ||||
| } | ||||
| 
 | ||||
| class Options | ||||
| @ -197,6 +223,8 @@ public: | ||||
| 	bool inputLimits = false; | ||||
| 	bool bigData = false; | ||||
| 	bool wallet = false; | ||||
| 	bool nonetwork = false; | ||||
| 	bool nodag = true; | ||||
| 	/// @}
 | ||||
| 
 | ||||
| 	/// Get reference to options
 | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
| #include <thread> | ||||
| #include <boost/test/unit_test.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <libdevcrypto/Common.h> | ||||
| #include <libtestutils/Common.h> | ||||
| #include <libtestutils/BlockChainLoader.h> | ||||
| #include <libtestutils/FixedClient.h> | ||||
| @ -116,3 +117,13 @@ void ParallelClientBaseFixture::enumerateClients(std::function<void(Json::Value | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| MoveNonceToTempDir::MoveNonceToTempDir() | ||||
| { | ||||
| 	crypto::Nonce::setSeedFilePath(m_dir.path() + "/seed"); | ||||
| } | ||||
| 
 | ||||
| MoveNonceToTempDir::~MoveNonceToTempDir() | ||||
| { | ||||
| 	crypto::Nonce::reset(); | ||||
| } | ||||
|  | ||||
| @ -24,6 +24,7 @@ | ||||
| #include <functional> | ||||
| #include <string> | ||||
| #include <json/json.h> | ||||
| #include <libdevcore/TransientDirectory.h> | ||||
| #include <libethereum/BlockChain.h> | ||||
| #include <libethereum/ClientBase.h> | ||||
| 
 | ||||
| @ -78,5 +79,13 @@ struct JsonRpcFixture: public ClientBaseFixture | ||||
| 	 | ||||
| }; | ||||
| 
 | ||||
| struct MoveNonceToTempDir | ||||
| { | ||||
| 	MoveNonceToTempDir(); | ||||
| 	~MoveNonceToTempDir(); | ||||
| private: | ||||
| 	TransientDirectory m_dir; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(location_test) | ||||
| 	AssemblyItems items = compileContract(sourceCode); | ||||
| 	vector<SourceLocation> locations = | ||||
| 		vector<SourceLocation>(17, SourceLocation(2, 75, n)) + | ||||
| 		vector<SourceLocation>(14, SourceLocation(20, 72, n)) + | ||||
| 		vector<SourceLocation>(26, SourceLocation(20, 72, n)) + | ||||
| 		vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + | ||||
| 		vector<SourceLocation>(4, SourceLocation(58, 67, n)) + | ||||
| 		vector<SourceLocation>(3, SourceLocation(20, 72, n)); | ||||
|  | ||||
| @ -1726,7 +1726,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_in_calls) | ||||
| 	BOOST_CHECK(callContractFunction("callHelper(bytes2,bool)", string("\0a", 2), true) == encodeArgs(string("\0a\0\0\0", 5))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(constructor_arguments) | ||||
| BOOST_AUTO_TEST_CASE(constructor_arguments_internal) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Helper { | ||||
| @ -1749,8 +1749,28 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) | ||||
| 			function getName() returns (bytes3 ret) { return h.getName(); } | ||||
| 		})"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	BOOST_REQUIRE(callContractFunction("getFlag()") == encodeArgs(true)); | ||||
| 	BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); | ||||
| 	BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); | ||||
| 	BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(constructor_arguments_external) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			bytes3 name; | ||||
| 			bool flag; | ||||
| 
 | ||||
| 			function Main(bytes3 x, bool f) { | ||||
| 				name = x; | ||||
| 				flag = f; | ||||
| 			} | ||||
| 			function getName() returns (bytes3 ret) { return name; } | ||||
| 			function getFlag() returns (bool ret) { return flag; } | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main", encodeArgs("abc", true)); | ||||
| 	BOOST_CHECK(callContractFunction("getFlag()") == encodeArgs(true)); | ||||
| 	BOOST_CHECK(callContractFunction("getName()") == encodeArgs("abc")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(functions_called_by_constructor) | ||||
| @ -2420,7 +2440,7 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage) | ||||
| 	callContractFunction("deposit()"); | ||||
| 	BOOST_REQUIRE_EQUAL(m_logs.size(), 1); | ||||
| 	BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); | ||||
| 	BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 3) + asBytes("ABC")); | ||||
| 	BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 3, string("ABC"))); | ||||
| 	BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); | ||||
| 	BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(uint256,bytes,uint256)"))); | ||||
| } | ||||
| @ -4166,7 +4186,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	BOOST_CHECK(compileAndRunWthoutCheck(sourceCode, 0, "A").empty()); | ||||
| 	BOOST_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A").empty()); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(positive_integers_to_signed) | ||||
| @ -4232,6 +4252,324 @@ BOOST_AUTO_TEST_CASE(reusing_memory) | ||||
| 	BOOST_REQUIRE(callContractFunction("f(uint256)", 0x34) == encodeArgs(dev::sha3(dev::toBigEndian(u256(0x34))))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(return_string) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			string public s; | ||||
| 			function set(string _s) external { | ||||
| 				s = _s; | ||||
| 			} | ||||
| 			function get1() returns (string r) { | ||||
| 				return s; | ||||
| 			} | ||||
| 			function get2() returns (string r) { | ||||
| 				r = s; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s("Julia"); | ||||
| 	bytes args = encodeArgs(u256(0x20), u256(s.length()), s); | ||||
| 	BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("get1()") == args); | ||||
| 	BOOST_CHECK(callContractFunction("get2()") == args); | ||||
| 	BOOST_CHECK(callContractFunction("s()") == args); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(return_multiple_strings_of_various_sizes) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			string public s1; | ||||
| 			string public s2; | ||||
| 			function set(string _s1, uint x, string _s2) external returns (uint) { | ||||
| 				s1 = _s1; | ||||
| 				s2 = _s2; | ||||
| 				return x; | ||||
| 			} | ||||
| 			function get() returns (string r1, string r2) { | ||||
| 				r1 = s1; | ||||
| 				r2 = s2; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s1( | ||||
| 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" | ||||
| 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" | ||||
| 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" | ||||
| 		"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" | ||||
| 	); | ||||
| 	string s2( | ||||
| 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" | ||||
| 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" | ||||
| 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" | ||||
| 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" | ||||
| 		"ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ" | ||||
| 	); | ||||
| 	vector<size_t> lengthes{0, 30, 32, 63, 64, 65, 210, 300}; | ||||
| 	for (auto l1: lengthes) | ||||
| 		for (auto l2: lengthes) | ||||
| 		{ | ||||
| 			bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); | ||||
| 			bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2)); | ||||
| 			bytes args = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn1.size())) + dyn1 + dyn2; | ||||
| 			BOOST_REQUIRE( | ||||
| 				callContractFunction("set(string,uint256,string)", asString(args)) == | ||||
| 				encodeArgs(u256(l1)) | ||||
| 			); | ||||
| 			bytes result = encodeArgs(u256(0x40), u256(0x40 + dyn1.size())) + dyn1 + dyn2; | ||||
| 			BOOST_CHECK(callContractFunction("get()") == result); | ||||
| 			BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); | ||||
| 			BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); | ||||
| 		} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(accessor_involving_strings) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			struct stringData { string a; uint b; string c; } | ||||
| 			mapping(uint => stringData[]) public data; | ||||
| 			function set(uint x, uint y, string a, uint b, string c) external returns (bool) { | ||||
| 				data[x].length = y + 1; | ||||
| 				data[x][y].a = a; | ||||
| 				data[x][y].b = b; | ||||
| 				data[x][y].c = c; | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"); | ||||
| 	bytes s1Data = encodeArgs(u256(s1.length()), s1); | ||||
| 	bytes s2Data = encodeArgs(u256(s2.length()), s2); | ||||
| 	u256 b = 765; | ||||
| 	u256 x = 7; | ||||
| 	u256 y = 123; | ||||
| 	bytes args = encodeArgs(x, y, u256(0xa0), b, u256(0xa0 + s1Data.size()), s1Data, s2Data); | ||||
| 	bytes result = encodeArgs(u256(0x60), b, u256(0x60 + s1Data.size()), s1Data, s2Data); | ||||
| 	BOOST_REQUIRE(callContractFunction("set(uint256,uint256,string,uint256,string)", asString(args)) == encodeArgs(true)); | ||||
| 	BOOST_REQUIRE(callContractFunction("data(uint256,uint256)", x, y) == result); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(bytes_in_function_calls) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			string public s1; | ||||
| 			string public s2; | ||||
| 			function set(string _s1, uint x, string _s2) returns (uint) { | ||||
| 				s1 = _s1; | ||||
| 				s2 = _s2; | ||||
| 				return x; | ||||
| 			} | ||||
| 			function setIndirectFromMemory(string _s1, uint x, string _s2) returns (uint) { | ||||
| 				return this.set(_s1, x, _s2); | ||||
| 			} | ||||
| 			function setIndirectFromCalldata(string _s1, uint x, string _s2) external returns (uint) { | ||||
| 				return this.set(_s1, x, _s2); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ"); | ||||
| 	vector<size_t> lengthes{0, 31, 64, 65}; | ||||
| 	for (auto l1: lengthes) | ||||
| 		for (auto l2: lengthes) | ||||
| 		{ | ||||
| 			bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); | ||||
| 			bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2)); | ||||
| 			bytes args1 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn1.size())) + dyn1 + dyn2; | ||||
| 			BOOST_REQUIRE( | ||||
| 				callContractFunction("setIndirectFromMemory(string,uint256,string)", asString(args1)) == | ||||
| 				encodeArgs(u256(l1)) | ||||
| 			); | ||||
| 			BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1); | ||||
| 			BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2); | ||||
| 			// swapped
 | ||||
| 			bytes args2 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn2.size())) + dyn2 + dyn1; | ||||
| 			BOOST_REQUIRE( | ||||
| 				callContractFunction("setIndirectFromCalldata(string,uint256,string)", asString(args2)) == | ||||
| 				encodeArgs(u256(l1)) | ||||
| 			); | ||||
| 			BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn2); | ||||
| 			BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn1); | ||||
| 		} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(return_bytes_internal) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			bytes s1; | ||||
| 			function doSet(bytes _s1) returns (bytes _r1) { | ||||
| 				s1 = _s1; | ||||
| 				_r1 = s1; | ||||
| 			} | ||||
| 			function set(bytes _s1) external returns (uint _r, bytes _r1) { | ||||
| 				_r1 = doSet(_s1); | ||||
| 				_r = _r1.length; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	vector<size_t> lengthes{0, 31, 64, 65}; | ||||
| 	for (auto l1: lengthes) | ||||
| 	{ | ||||
| 		bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1)); | ||||
| 		bytes args1 = encodeArgs(u256(0x20)) + dyn1; | ||||
| 		BOOST_REQUIRE( | ||||
| 			callContractFunction("set(bytes)", asString(args1)) == | ||||
| 			encodeArgs(u256(l1), u256(0x40)) + dyn1 | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(bytes_index_access_memory) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Main { | ||||
| 			function f(bytes _s1, uint i1, uint i2, uint i3) returns (byte c1, byte c2, byte c3) { | ||||
| 				c1 = _s1[i1]; | ||||
| 				c2 = intern(_s1, i2); | ||||
| 				c3 = internIndirect(_s1)[i3]; | ||||
| 			} | ||||
| 			function intern(bytes _s1, uint i) returns (byte c) { | ||||
| 				return _s1[i]; | ||||
| 			} | ||||
| 			function internIndirect(bytes _s1) returns (bytes) { | ||||
| 				return _s1; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Main"); | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	bytes dyn1 = encodeArgs(u256(s1.length()), s1); | ||||
| 	bytes args1 = encodeArgs(u256(0x80), u256(3), u256(4), u256(5)) + dyn1; | ||||
| 	BOOST_REQUIRE( | ||||
| 		callContractFunction("f(bytes,uint256,uint256,uint256)", asString(args1)) == | ||||
| 		encodeArgs(string{s1[3]}, string{s1[4]}, string{s1[5]}) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(bytes_in_constructors_unpacker) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Test { | ||||
| 			uint public m_x; | ||||
| 			bytes public m_s; | ||||
| 			function Test(uint x, bytes s) { | ||||
| 				m_x = x; | ||||
| 				m_s = s; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	bytes dyn1 = encodeArgs(u256(s1.length()), s1); | ||||
| 	u256 x = 7; | ||||
| 	bytes args1 = encodeArgs(x, u256(0x40)) + dyn1; | ||||
| 	compileAndRun(sourceCode, 0, "Test", args1); | ||||
| 	BOOST_REQUIRE(callContractFunction("m_x()") == encodeArgs(x)); | ||||
| 	BOOST_REQUIRE(callContractFunction("m_s()") == encodeArgs(u256(0x20)) + dyn1); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract Base { | ||||
| 			uint public m_x; | ||||
| 			bytes m_s; | ||||
| 			function Base(uint x, bytes s) { | ||||
| 				m_x = x; | ||||
| 				m_s = s; | ||||
| 			} | ||||
| 			function part(uint i) returns (byte) { | ||||
| 				return m_s[i]; | ||||
| 			} | ||||
| 		} | ||||
| 		contract Main is Base { | ||||
| 			function Main(bytes s, uint x) Base(x, s){}//f(s)) {}
 | ||||
| 			function f(bytes s) returns (bytes) { | ||||
| 				return s; | ||||
| 			} | ||||
| 		} | ||||
| 		contract Creator { | ||||
| 			function f(uint x, bytes s) returns (uint r, byte ch) { | ||||
| 				var c = new Main(s, x); | ||||
| 				r = c.m_x(); | ||||
| 				ch = c.part(x); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Creator"); | ||||
| 	string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); | ||||
| 	bytes dyn1 = encodeArgs(u256(s1.length()), s1); | ||||
| 	u256 x = 7; | ||||
| 	bytes args1 = encodeArgs(x, u256(0x40)) + dyn1; | ||||
| 	BOOST_REQUIRE( | ||||
| 		callContractFunction("f(uint256,bytes)", asString(args1)) == | ||||
| 		encodeArgs(x, string{s1[unsigned(x)]}) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(storage_array_ref) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract BinarySearch { | ||||
| 		  /// Finds the position of _value in the sorted list _data.
 | ||||
| 		  /// Note that "internal" is important here, because storage references only work for internal or private functions
 | ||||
| 		  function find(uint[] storage _data, uint _value) internal returns (uint o_position) { | ||||
| 			return find(_data, 0, _data.length, _value); | ||||
| 		  } | ||||
| 		  function find(uint[] storage _data, uint _begin, uint _len, uint _value) private returns (uint o_position) { | ||||
| 			if (_len == 0 || (_len == 1 && _data[_begin] != _value)) | ||||
| 			  return uint(-1); // failure
 | ||||
| 			uint halfLen = _len / 2; | ||||
| 			uint v = _data[_begin + halfLen]; | ||||
| 			if (_value < v) | ||||
| 			  return find(_data, _begin, halfLen, _value); | ||||
| 			else if (_value > v) | ||||
| 			  return find(_data, _begin + halfLen + 1, halfLen - 1, _value); | ||||
| 			else | ||||
| 			  return _begin + halfLen; | ||||
| 		  } | ||||
| 		} | ||||
| 
 | ||||
| 		contract Store is BinarySearch { | ||||
| 			uint[] data; | ||||
| 			function add(uint v) { | ||||
| 				data.length++; | ||||
| 				data[data.length - 1] = v; | ||||
| 			} | ||||
| 			function find(uint v) returns (uint) { | ||||
| 				return find(data, v); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode, 0, "Store"); | ||||
| 	BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(-1))); | ||||
| 	BOOST_REQUIRE(callContractFunction("add(uint256)", u256(7)) == encodeArgs()); | ||||
| 	BOOST_REQUIRE(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(11)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(17)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(27)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(31)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(32)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(66)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("add(uint256)", u256(177)) == encodeArgs()); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(7)) == encodeArgs(u256(0))); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(27)) == encodeArgs(u256(3))); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(32)) == encodeArgs(u256(5))); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(176)) == encodeArgs(u256(-1))); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(0)) == encodeArgs(u256(-1))); | ||||
| 	BOOST_CHECK(callContractFunction("find(uint256)", u256(400)) == encodeArgs(u256(-1))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -190,6 +190,17 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) | ||||
| 	BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) | ||||
| { | ||||
| 	char const* text = R"( | ||||
| 		contract test { | ||||
| 			struct s1 { uint a; } | ||||
| 			struct s2 { s1 x; s1 y; } | ||||
| 		} | ||||
| 	)"; | ||||
| 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) | ||||
| { | ||||
| 	char const* text = "contract test {\n" | ||||
| @ -1976,6 +1987,19 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) | ||||
| 	BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract C { | ||||
| 			function f(uint) returns (string); | ||||
| 			function g() { | ||||
| 				var x = this.f(2); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -77,13 +77,13 @@ BOOST_AUTO_TEST_CASE(storage_layout_mapping) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(storage_layout_arrays) | ||||
| { | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(1), 32).getStorageSize() == 1); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(1), 33).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(2), 31).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(7), 8).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(7), 9).getStorageSize() == 3); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(31), 9).getStorageSize() == 9); | ||||
| 	BOOST_CHECK(ArrayType(ReferenceType::Location::Storage, make_shared<FixedBytesType>(32), 9).getStorageSize() == 9); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(1), 32).getStorageSize() == 1); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(1), 33).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(2), 31).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(7), 8).getStorageSize() == 2); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(7), 9).getStorageSize() == 3); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(31), 9).getStorageSize() == 9); | ||||
| 	BOOST_CHECK(ArrayType(DataLocation::Storage, make_shared<FixedBytesType>(32), 9).getStorageSize() == 9); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
|  | ||||
| @ -42,19 +42,29 @@ class ExecutionFramework | ||||
| public: | ||||
| 	ExecutionFramework() { g_logVerbosity = 0; } | ||||
| 
 | ||||
| 	bytes const& compileAndRunWthoutCheck(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") | ||||
| 	bytes const& compileAndRunWithoutCheck( | ||||
| 		std::string const& _sourceCode, | ||||
| 		u256 const& _value = 0, | ||||
| 		std::string const& _contractName = "", | ||||
| 		bytes const& _arguments = bytes() | ||||
| 	) | ||||
| 	{ | ||||
| 		m_compiler.reset(false, m_addStandardSources); | ||||
| 		m_compiler.addSource("", _sourceCode); | ||||
| 		ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed"); | ||||
| 		bytes code = m_compiler.getBytecode(_contractName); | ||||
| 		sendMessage(code, true, _value); | ||||
| 		sendMessage(code + _arguments, true, _value); | ||||
| 		return m_output; | ||||
| 	} | ||||
| 
 | ||||
| 	bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") | ||||
| 	bytes const& compileAndRun( | ||||
| 		std::string const& _sourceCode, | ||||
| 		u256 const& _value = 0, | ||||
| 		std::string const& _contractName = "", | ||||
| 		bytes const& _arguments = bytes() | ||||
| 	) | ||||
| 	{ | ||||
| 		compileAndRunWthoutCheck(_sourceCode, _value, _contractName); | ||||
| 		compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments); | ||||
| 		BOOST_REQUIRE(!m_output.empty()); | ||||
| 		return m_output; | ||||
| 	} | ||||
| @ -174,11 +184,11 @@ protected: | ||||
| 			BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); | ||||
| 			BOOST_REQUIRE(!executive.call(m_contractAddress, m_sender, _value, m_gasPrice, &_data, m_gas)); | ||||
| 		} | ||||
| 		BOOST_REQUIRE(executive.go()); | ||||
| 		BOOST_REQUIRE(executive.go(/* DEBUG eth::Executive::simpleTrace() */)); | ||||
| 		m_state.noteSending(m_sender); | ||||
| 		executive.finalize(); | ||||
| 		m_gasUsed = executive.gasUsed(); | ||||
| 		m_output = std::move(res.output); // FIXME: Looks like Framework needs ExecutiveResult embedded
 | ||||
| 		m_gasUsed = res.gasUsed; | ||||
| 		m_output = std::move(res.output); | ||||
| 		m_logs = executive.logs(); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user