diff --git a/TestHelper.cpp b/TestHelper.cpp index 6c1db8eea..698f35122 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -178,7 +178,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptio { stateOptions.m_bHasBalance = true; if (bigint(o["balance"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") ); balance = toInt(o["balance"]); } @@ -186,7 +186,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptio { stateOptions.m_bHasNonce = true; if (bigint(o["nonce"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") ); nonce = toInt(o["nonce"]); } @@ -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()) - TBOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!")); + BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!")); } } @@ -246,13 +246,13 @@ void ImportTest::importTransaction(json_spirit::mObject& _o) assert(_o.count("data") > 0); if (bigint(_o["nonce"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") ); if (bigint(_o["gasPrice"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") ); if (bigint(_o["gasLimit"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") ); if (bigint(_o["value"].get_str()) >= c_max256plus1) - TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") ); + BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") ); m_transaction = _o["to"].get_str().empty() ? Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())) : @@ -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")); } @@ -533,24 +533,25 @@ void checkOutput(bytes const& _output, json_spirit::mObject& _o) void checkStorage(map _expectedStore, map _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); } } @@ -568,14 +569,14 @@ void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) 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,7 +599,7 @@ void userDefinedTest(std::function doTests) cnote << "Testing user defined test: " << filename; json_spirit::mValue v; string s = contentsString(filename); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + filename + " is empty. "); json_spirit::read_string(s, v); json_spirit::mObject oSingleTest; @@ -616,11 +617,11 @@ void userDefinedTest(std::function 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()); } } @@ -640,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()); } } @@ -660,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()); } } diff --git a/TestHelper.h b/TestHelper.h index c21429ef4..73b560aa0 100644 --- a/TestHelper.h +++ b/TestHelper.h @@ -32,21 +32,21 @@ #include #ifdef NOBOOST - #define TBOOST_THROW_EXCEPTION(arg) throw dev::Exception(); #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_THROW_EXCEPTION(arg) BOOST_THROW_EXCEPTION(arg) #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 diff --git a/libsolidity/SolidityEndToEndTest.cpp b/libsolidity/SolidityEndToEndTest.cpp index a839aa027..d397dc595 100644 --- a/libsolidity/SolidityEndToEndTest.cpp +++ b/libsolidity/SolidityEndToEndTest.cpp @@ -4355,6 +4355,168 @@ BOOST_AUTO_TEST_CASE(accessor_involving_strings) 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 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 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"( diff --git a/libsolidity/SolidityNameAndTypeResolution.cpp b/libsolidity/SolidityNameAndTypeResolution.cpp index afa8b727f..765593c59 100644 --- a/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1987,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() }