diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/RPCSession.cpp | 6 | ||||
-rw-r--r-- | test/TestHelper.cpp | 2 | ||||
-rw-r--r-- | test/TestHelper.h | 1 | ||||
-rw-r--r-- | test/boostTest.cpp | 19 | ||||
-rw-r--r-- | test/liblll/Compiler.cpp | 128 | ||||
-rw-r--r-- | test/liblll/EndToEndTest.cpp | 86 | ||||
-rw-r--r-- | test/libsolidity/AnalysisFramework.cpp | 45 | ||||
-rw-r--r-- | test/libsolidity/AnalysisFramework.h | 11 | ||||
-rw-r--r-- | test/libsolidity/GasMeter.cpp | 10 | ||||
-rw-r--r-- | test/libsolidity/SMTChecker.cpp | 86 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 87 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 150 |
12 files changed, 563 insertions, 68 deletions
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index c4fbfefb..768c8c4b 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -217,11 +217,11 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) { "sealEngine": "NoProof", "params": { - "accountStartNonce": "0x", + "accountStartNonce": "0x00", "maximumExtraDataSize": "0x1000000", "blockReward": "0x", - "allowFutureBlocks": "1", - "homsteadForkBlock": "0x00", + "allowFutureBlocks": true, + "homesteadForkBlock": "0x00", "EIP150ForkBlock": "0x00", "EIP158ForkBlock": "0x00" }, diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 094b59c6..c8747a06 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -45,6 +45,8 @@ Options::Options() showMessages = true; else if (string(suite.argv[i]) == "--no-ipc") disableIPC = true; + else if (string(suite.argv[i]) == "--no-smt") + disableSMT = true; if (!disableIPC && ipcPath.empty()) if (auto path = getenv("ETH_TEST_IPC")) diff --git a/test/TestHelper.h b/test/TestHelper.h index d50568ad..d25c5cd8 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -35,6 +35,7 @@ struct Options: boost::noncopyable bool showMessages = false; bool optimize = false; bool disableIPC = false; + bool disableSMT = false; static Options const& get(); diff --git a/test/boostTest.cpp b/test/boostTest.cpp index d8c5b678..7b452e06 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -39,6 +39,17 @@ using namespace boost::unit_test; +namespace +{ +void removeTestSuite(std::string const& _name) +{ + master_test_suite_t& master = framework::master_test_suite(); + auto id = master.get(_name); + assert(id != INV_TEST_UNIT_ID); + master.remove(id); +} +} + test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) { master_test_suite_t& master = framework::master_test_suite(); @@ -57,12 +68,10 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityEndToEndTest", "SolidityOptimizer" }) - { - auto id = master.get(suite); - assert(id != INV_TEST_UNIT_ID); - master.remove(id); - } + removeTestSuite(suite); } + if (dev::test::Options::get().disableSMT) + removeTestSuite("SMTChecker"); return 0; } diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp new file mode 100644 index 00000000..2d66bce1 --- /dev/null +++ b/test/liblll/Compiler.cpp @@ -0,0 +1,128 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @author Alex Beregszaszi + * @date 2017 + * Unit tests for the LLL compiler. + */ + +#include <string> +#include <memory> +#include <boost/test/unit_test.hpp> +#include <liblll/Compiler.h> + +using namespace std; + +namespace dev +{ +namespace lll +{ +namespace test +{ + +namespace +{ + +bool successCompile(std::string const& _sourceCode) +{ + std::vector<std::string> errors; + bytes bytecode = eth::compileLLL(_sourceCode, false, &errors); + if (!errors.empty()) + return false; + if (bytecode.empty()) + return false; + return true; +} + +} + +BOOST_AUTO_TEST_SUITE(LLLCompiler) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* sourceCode = "1"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_valid) +{ + char const* sourceCode = R"( + (switch (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (panic)) + )"; + BOOST_CHECK(successCompile(sourceCode)); + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (origin)) + )"; + BOOST_CHECK(successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_invalid_arg_count) +{ + char const* sourceCode = R"( + (switch) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) +{ + // cannot return stack items if the default case is not present + char const* sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (origin) + 2 (origin) + (panic)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); + // return count mismatch + sourceCode = R"( + (switch + 1 (panic) + 2 (panic) + (origin)) + )"; + BOOST_CHECK(!successCompile(sourceCode)); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 9292d963..1a5bb490 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -215,6 +215,92 @@ BOOST_AUTO_TEST_CASE(conditional_nested_then) BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); } +BOOST_AUTO_TEST_CASE(conditional_switch) +{ + char const* sourceCode = R"( + (returnlll + (seq + (def 'input (calldataload 0x04)) + ;; Calculates width in bytes of utf-8 characters. + (return + (switch + (< input 0x80) 1 + (< input 0xE0) 2 + (< input 0xF0) 3 + (< input 0xF8) 4 + (< input 0xFC) 5 + 6)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); + BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); + BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); + BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); + BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_two_args) +{ + char const* sourceCode = R"( + (returnlll + (seq + (switch (= (calldataload 0x04) 1) [0]:42) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_with_deposit) +{ + char const* sourceCode = R"( + (returnlll + (return + (switch (= (calldataload 0x04) 1) 41 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + +BOOST_AUTO_TEST_CASE(conditional_switch_three_args_no_deposit) +{ + char const* sourceCode = R"( + (returnlll + (switch + (= (calldataload 0x04) 1) (return 41) + (return 42))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); +} + BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 5f5f6411..3bdc40a0 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -25,6 +25,8 @@ #include <libsolidity/ast/AST.h> +#include <libsolidity/parsing/Scanner.h> + #include <libdevcore/SHA3.h> #include <boost/test/unit_test.hpp> @@ -46,8 +48,7 @@ AnalysisFramework::parseAnalyseAndReturnError( m_compiler.addSource("", _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source); if (!m_compiler.parse()) { - printErrors(); - BOOST_ERROR("Parsing contract failed in analysis test suite."); + BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors()); } m_compiler.analyze(); @@ -56,15 +57,24 @@ AnalysisFramework::parseAnalyseAndReturnError( for (auto const& currentError: m_compiler.errors()) { solAssert(currentError->comment(), ""); - if (currentError->comment()->find("This is a pre-release compiler version") == 0) - continue; + if (currentError->type() == Error::Type::Warning) + { + bool ignoreWarning = false; + for (auto const& filter: m_warningsToFilter) + if (currentError->comment()->find(filter) == 0) + { + ignoreWarning = true; + break; + } + if (ignoreWarning) + continue; + } if (_reportWarnings || (currentError->type() != Error::Type::Warning)) { if (firstError && !_allowMultipleErrors) { - printErrors(); - BOOST_FAIL("Multiple errors found."); + BOOST_FAIL("Multiple errors found: " + formatErrors()); } if (!firstError) firstError = currentError; @@ -78,7 +88,10 @@ SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) { auto sourceAndError = parseAnalyseAndReturnError(_source); BOOST_REQUIRE(!!sourceAndError.first); - BOOST_REQUIRE(!sourceAndError.second); + string message; + if (sourceAndError.second) + message = "Unexpected error: " + formatError(*sourceAndError.second); + BOOST_REQUIRE_MESSAGE(!sourceAndError.second, message); return sourceAndError.first; } @@ -91,17 +104,23 @@ Error AnalysisFramework::expectError(std::string const& _source, bool _warning, { auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple); BOOST_REQUIRE(!!sourceAndError.second); - BOOST_REQUIRE(!!sourceAndError.first); + BOOST_REQUIRE_MESSAGE(!!sourceAndError.first, "Expected error, but no error happened."); return *sourceAndError.second; } -void AnalysisFramework::printErrors() +string AnalysisFramework::formatErrors() { + string message; for (auto const& error: m_compiler.errors()) - SourceReferenceFormatter::printExceptionInformation( - std::cerr, - *error, - (error->type() == Error::Type::Warning) ? "Warning" : "Error", + message += formatError(*error); + return message; +} + +string AnalysisFramework::formatError(Error const& _error) +{ + return SourceReferenceFormatter::formatExceptionInformation( + _error, + (_error.type() == Error::Type::Warning) ? "Warning" : "Error", [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); } ); } diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index 172ae01b..a566ba1d 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -45,7 +45,7 @@ class AnalysisFramework { protected: - std::pair<SourceUnit const*, std::shared_ptr<Error const>> + virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>> parseAnalyseAndReturnError( std::string const& _source, bool _reportWarnings = false, @@ -57,7 +57,8 @@ protected: bool success(std::string const& _source); Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); - void printErrors(); + std::string formatErrors(); + std::string formatError(Error const& _error); static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name); static FunctionTypePointer retrieveFunctionBySignature( @@ -65,6 +66,7 @@ protected: std::string const& _signature ); + std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"}; dev::solidity::CompilerStack m_compiler; }; @@ -104,7 +106,10 @@ CHECK_ERROR_OR_WARNING(text, Warning, substring, true, true) do \ { \ auto sourceAndError = parseAnalyseAndReturnError((text), true); \ - BOOST_CHECK(sourceAndError.second == nullptr); \ + std::string message; \ + if (sourceAndError.second) \ + message = formatError(*sourceAndError.second); \ + BOOST_CHECK_MESSAGE(!sourceAndError.second, message); \ } \ while(0) diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index b759678f..c2886f5b 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -21,7 +21,6 @@ */ #include <test/libsolidity/SolidityExecutionFramework.h> -#include <libevmasm/EVMSchedule.h> #include <libevmasm/GasMeter.h> #include <libevmasm/KnownState.h> #include <libevmasm/PathGasMeter.h> @@ -63,15 +62,13 @@ public: void testCreationTimeGas(string const& _sourceCode) { - EVMSchedule schedule; - compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); PathGasMeter meter(*m_compiler.assemblyItems()); GasMeter::GasConsumption gas = meter.estimateMax(0, state); u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size()); // costs for deployment - gas += bytecodeSize * schedule.createDataGas; + gas += bytecodeSize * GasCosts::createDataGas; // costs for transaction gas += gasForTransaction(m_compiler.object().bytecode, true); @@ -103,10 +100,9 @@ public: static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation) { - EVMSchedule schedule; - GasMeter::GasConsumption gas = _isCreation ? schedule.txCreateGas : schedule.txGas; + GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas; for (auto i: _data) - gas += i != 0 ? schedule.txDataNonZeroGas : schedule.txDataZeroGas; + gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas; return gas; } diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp new file mode 100644 index 00000000..d58f296f --- /dev/null +++ b/test/libsolidity/SMTChecker.cpp @@ -0,0 +1,86 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for the SMT checker. + */ + +#include <test/libsolidity/AnalysisFramework.h> + +#include <boost/test/unit_test.hpp> + +#include <string> + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerFramework: public AnalysisFramework +{ +public: + SMTCheckerFramework() + { + m_warningsToFilter.push_back("Experimental features are turned on."); + } + +protected: + virtual std::pair<SourceUnit const*, std::shared_ptr<Error const>> + parseAnalyseAndReturnError( + std::string const& _source, + bool _reportWarnings = false, + bool _insertVersionPragma = true, + bool _allowMultipleErrors = false + ) + { + return AnalysisFramework::parseAnalyseAndReturnError( + "pragma experimental SMTChecker;\n" + _source, + _reportWarnings, + _insertVersionPragma, + _allowMultipleErrors + ); + } +}; + +BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + string text = R"( + contract C { } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(simple_overflow) +{ + string text = R"( + contract C { + function f(uint a, uint b) public pure returns (uint) { return a + b; } + } + )"; + CHECK_WARNING(text, "Overflow (resulting value larger than"); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 82dedf85..35916ec7 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1457,7 +1457,7 @@ BOOST_AUTO_TEST_CASE(msg_sig) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) @@ -1473,7 +1473,7 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("foo(uint256)"), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); + ABI_CHECK(callContractFunction("foo(uint256)", 0), encodeArgs(asString(FixedHash<4>(dev::keccak256("foo(uint256)")).asBytes()))); } BOOST_AUTO_TEST_CASE(now) @@ -1494,7 +1494,7 @@ BOOST_AUTO_TEST_CASE(now) size_t endTime = blockTimestamp(endBlock); BOOST_CHECK(startBlock != endBlock); BOOST_CHECK(startTime != endTime); - BOOST_CHECK(ret == encodeArgs(true, endTime)); + ABI_CHECK(ret, encodeArgs(true, endTime)); } BOOST_AUTO_TEST_CASE(type_conversions_cleanup) @@ -3090,7 +3090,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) char const* sourceCode = R"( contract ClientReceipt { event Deposit(address indexed _from, bytes32 indexed _id, uint indexed _value, uint indexed _value2, bytes32 data) anonymous; - function deposit(bytes32 _id, bool _manually) payable { + function deposit(bytes32 _id) payable { Deposit(msg.sender, _id, msg.value, 2, "abc"); } } @@ -3098,7 +3098,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) compileAndRun(sourceCode); u256 value(18); u256 id(0x1234); - callContractFunctionWithValue("deposit(bytes32,bool)", value, id); + callContractFunctionWithValue("deposit(bytes32)", value, id); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK(m_logs[0].data == encodeArgs("abc")); @@ -3757,11 +3757,11 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) compileAndRun(sourceCode); string data = "123456789012345678901234567890123"; BOOST_CHECK(storageEmpty(m_contractAddress)); - ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); ABI_CHECK(callContractFunction("copy()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); - ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data), encodeArgs(true)); + ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true)); BOOST_CHECK(!storageEmpty(m_contractAddress)); ABI_CHECK(callContractFunction("del()"), encodeArgs(true)); BOOST_CHECK(storageEmpty(m_contractAddress)); @@ -5185,7 +5185,7 @@ BOOST_AUTO_TEST_CASE(packed_storage_signed) } )"; compileAndRun(sourceCode); - BOOST_CHECK( callContractFunction("test()") == encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); + ABI_CHECK(callContractFunction("test()"), encodeArgs(u256(-2), u256(4), u256(-112), u256(0))); } BOOST_AUTO_TEST_CASE(external_types_in_calls) @@ -5540,7 +5540,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund) } } )"; - BOOST_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A").empty()); + ABI_CHECK(compileAndRunWithoutCheck(sourceCode, 0, "A"), encodeArgs()); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed) @@ -6505,31 +6505,32 @@ BOOST_AUTO_TEST_CASE(string_as_mapping_key) "1" }; for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "set(string,uint256)", u256(0x40), u256(7 + i), u256(strings[i].size()), strings[i] - ) == encodeArgs()); + ), encodeArgs()); for (unsigned i = 0; i < strings.size(); i++) - BOOST_CHECK(callContractFunction( + ABI_CHECK(callContractFunction( "get(string)", u256(0x20), u256(strings[i].size()), strings[i] - ) == encodeArgs(u256(7 + i))); + ), encodeArgs(u256(7 + i))); } BOOST_AUTO_TEST_CASE(accessor_for_state_variable) { char const* sourceCode = R"( - contract Lotto{ + contract Lotto { uint public ticketPrice = 500; - })"; + } + )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(500))); } BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) @@ -6537,10 +6538,11 @@ BOOST_AUTO_TEST_CASE(accessor_for_const_state_variable) char const* sourceCode = R"( contract Lotto{ uint constant public ticketPrice = 555; - })"; + } + )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("ticketPrice()"), encodeArgs(u256(555))); } BOOST_AUTO_TEST_CASE(state_variable_under_contract_name) @@ -7402,7 +7404,7 @@ BOOST_AUTO_TEST_CASE(string_allocation_bug) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("p(uint256)"), encodeArgs( + ABI_CHECK(callContractFunction("p(uint256)", 0), encodeArgs( u256(0xbbbb), u256(0xcccc), u256(0x80), @@ -7913,7 +7915,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_call_assignment) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(2), u256(7))); } BOOST_AUTO_TEST_CASE(inline_assembly_function_call2) @@ -8776,8 +8778,8 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK( - callContractFunction("f()") == + ABI_CHECK( + callContractFunction("f()"), m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) ); } @@ -10120,9 +10122,9 @@ BOOST_AUTO_TEST_CASE(function_types_sig) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("g()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); - BOOST_CHECK(callContractFunction("h()") == encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(asString(FixedHash<4>(dev::keccak256("f()")).asBytes()))); } BOOST_AUTO_TEST_CASE(constant_string) @@ -10144,9 +10146,34 @@ BOOST_AUTO_TEST_CASE(constant_string) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("g()") == encodeDyn(string("\x03\x01\x02"))); - BOOST_CHECK(callContractFunction("h()") == encodeDyn(string("hello"))); + ABI_CHECK(callContractFunction("f()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("g()"), encodeDyn(string("\x03\x01\x02"))); + ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello"))); +} + +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* sourceCode = R"( + contract C { + function balance() returns (uint) { + return 1; + } + function transfer(uint amount) returns (uint) { + return amount; + } + } + contract D { + function f() returns (uint) { + return (new C()).balance(); + } + function g() returns (uint) { + return (new C()).transfer(5); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 39c47f9c..ed223678 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1395,6 +1395,61 @@ BOOST_AUTO_TEST_CASE(events_with_same_name) BOOST_CHECK(success(text)); } +BOOST_AUTO_TEST_CASE(events_with_same_name_unnamed_arguments) +{ + char const* text = R"( + contract test { + event A(uint); + event A(uint, uint); + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(events_with_same_name_different_types) +{ + char const* text = R"( + contract test { + event A(uint); + event A(bytes); + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint i); + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_anonymous) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint i) anonymous; + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + +BOOST_AUTO_TEST_CASE(double_event_declaration_ignores_indexed) +{ + char const* text = R"( + contract test { + event A(uint i); + event A(uint indexed i); + } + )"; + CHECK_ERROR(text, DeclarationError, "Event with same name and arguments defined twice."); +} + BOOST_AUTO_TEST_CASE(event_call) { char const* text = R"( @@ -2306,17 +2361,28 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); } -BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) +BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x) { char const* text = R"( contract C { address constant x = msg.sender; } )"; - // Change to TypeError for 0.5.0. CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); } +BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + + contract C { + address constant x = msg.sender; + } + )"; + CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); +} + BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) { char const* text = R"( @@ -2333,7 +2399,7 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) CHECK_ERROR(text, TypeError, "Index access for string is not possible."); } -BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant_0_4_x) { char const* text = R"( contract C { @@ -2341,10 +2407,22 @@ BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) uint constant y = x(); } )"; - // Change to TypeError for 0.5.0. CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); } +BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + + contract C { + function () constant returns (uint) x; + uint constant y = x(); + } + )"; + CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); +} + BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) { char const* text = R"( @@ -4135,6 +4213,8 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; CHECK_SUCCESS_NO_WARNINGS(text); + + // Test deprecation warning under < 0.5.0 text = R"( contract test { function f() pure public { @@ -4154,6 +4234,29 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } )"; CHECK_WARNING(text,"Use of unary + is deprecated"); + + // Test syntax error under 0.5.0 + text = R"( + pragma experimental "v0.5.0"; + contract test { + function f() pure public { + ufixed16x2 a = +3.25; + fixed16x2 b = -3.25; + a; b; + } + } + )"; + CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); + text = R"( + pragma experimental "v0.5.0"; + contract test { + function f(uint x) pure public { + uint y = +x; + y; + } + } + )"; + CHECK_ERROR(text, SyntaxError, "Use of unary + is deprecated"); } BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) @@ -4251,7 +4354,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Array with fractional length specified."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) @@ -4263,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) @@ -4275,7 +4378,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal"); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) @@ -6953,6 +7056,39 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide) CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* text = R"( + contract C { + function balance() returns (uint) { + this.balance; // to avoid pureness warning + return 1; + } + function transfer(uint amount) { + address(this).transfer(amount); // to avoid pureness warning + } + } + contract D { + function f() { + var x = (new C()).balance(); + x; + (new C()).transfer(5); + } + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(array_length_validation) +{ + char const* text = R"( + contract C { + uint[8**90] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); +} + BOOST_AUTO_TEST_SUITE_END() } |