diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/boostTest.cpp | 1 | ||||
| -rw-r--r-- | test/libdevcore/IndentedWriter.cpp | 75 | ||||
| -rw-r--r-- | test/libsolidity/ABIEncoderTests.cpp | 405 | ||||
| -rw-r--r-- | test/libsolidity/Imports.cpp | 9 | ||||
| -rw-r--r-- | test/libsolidity/Metadata.cpp | 30 | ||||
| -rw-r--r-- | test/libsolidity/SolidityABIJSON.cpp | 54 | ||||
| -rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 316 | ||||
| -rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 641 | ||||
| -rw-r--r-- | test/libsolidity/SolidityParser.cpp | 72 |
9 files changed, 1350 insertions, 253 deletions
diff --git a/test/boostTest.cpp b/test/boostTest.cpp index c2121940..d8c5b678 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -46,6 +46,7 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) if (dev::test::Options::get().disableIPC) { for (auto suite: { + "ABIEncoderTest", "SolidityAuctionRegistrar", "SolidityFixedFeeRegistrar", "SolidityWallet", diff --git a/test/libdevcore/IndentedWriter.cpp b/test/libdevcore/IndentedWriter.cpp new file mode 100644 index 00000000..a694aa1b --- /dev/null +++ b/test/libdevcore/IndentedWriter.cpp @@ -0,0 +1,75 @@ +/* + 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 IndentedWriter. + */ + +#include <libdevcore/IndentedWriter.h> + +#include "../TestHelper.h" + +using namespace std; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(IndentedWriterTest) + +BOOST_AUTO_TEST_CASE(empty) +{ + IndentedWriter iw; + BOOST_CHECK_EQUAL(iw.format(), "\n"); +} + +BOOST_AUTO_TEST_CASE(new_lines) +{ + IndentedWriter iw; + iw.newLine(); + BOOST_CHECK_EQUAL(iw.format(), "\n"); +} + +BOOST_AUTO_TEST_CASE(text_without_newline) +{ + IndentedWriter iw; + iw.add("Hello World"); + BOOST_CHECK_EQUAL(iw.format(), "Hello World\n"); +} + +BOOST_AUTO_TEST_CASE(text_with_newline) +{ + IndentedWriter iw; + iw.addLine("Hello World"); + BOOST_CHECK_EQUAL(iw.format(), "Hello World\n\n"); +} + +BOOST_AUTO_TEST_CASE(indent) +{ + IndentedWriter iw; + iw.addLine("Hello"); + iw.indent(); + iw.addLine("World"); + iw.unindent(); + iw.addLine("and everyone else"); + BOOST_CHECK_EQUAL(iw.format(), "Hello\n World\nand everyone else\n\n"); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp new file mode 100644 index 00000000..297c4ef0 --- /dev/null +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -0,0 +1,405 @@ +/* + 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 Solidity's ABI encoder. + */ + +#include <functional> +#include <string> +#include <tuple> +#include <boost/test/unit_test.hpp> +#include <libsolidity/interface/Exceptions.h> +#include <test/libsolidity/SolidityExecutionFramework.h> + +using namespace std; +using namespace std::placeholders; +using namespace dev::test; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +#define REQUIRE_LOG_DATA(DATA) do { \ + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); \ + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); \ + BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(DATA)); \ +} while (false) + +static string const NewEncoderPragma = "pragma experimental ABIEncoderV2;\n"; + +#define NEW_ENCODER(CODE) \ +{ \ + sourceCode = NewEncoderPragma + sourceCode; \ + { CODE } \ +} + +#define BOTH_ENCODERS(CODE) \ +{ \ + { CODE } \ + NEW_ENCODER(CODE) \ +} + +BOOST_FIXTURE_TEST_SUITE(ABIEncoderTest, SolidityExecutionFramework) + +BOOST_AUTO_TEST_CASE(both_encoders_macro) +{ + // This tests that the "both encoders macro" at least runs twice and + // modifies the source. + string sourceCode; + int runs = 0; + BOTH_ENCODERS(runs++;) + BOOST_CHECK(sourceCode == NewEncoderPragma); + BOOST_CHECK_EQUAL(runs, 2); +} + +BOOST_AUTO_TEST_CASE(value_types) +{ + string sourceCode = R"( + contract C { + event E(uint a, uint16 b, uint24 c, int24 d, bytes3 x, bool, C); + function f() { + bytes6 x = hex"1bababababa2"; + bool b; + assembly { b := 7 } + C c; + assembly { c := sub(0, 5) } + E(10, uint16(uint256(-2)), uint24(0x12121212), int24(int256(-1)), bytes3(x), b, c); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + 10, u256(65534), u256(0x121212), u256(-1), string("\x1b\xab\xab"), true, u160(u256(-5)) + )); + ) +} + +BOOST_AUTO_TEST_CASE(string_literal) +{ + string sourceCode = R"( + contract C { + event E(string, bytes20, string); + function f() { + E("abcdef", "abcde", "abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl"); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + 0x60, string("abcde"), 0xa0, + 6, string("abcdef"), + 0x8b, string("abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl") + )); + ) +} + + +BOOST_AUTO_TEST_CASE(enum_type_cleanup) +{ + string sourceCode = R"( + contract C { + enum E { A, B } + function f(uint x) returns (E en) { + assembly { en := x } + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", 0) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("f(uint256)", 1) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(uint256)", 2) == encodeArgs()); + ) +} + +BOOST_AUTO_TEST_CASE(conversion) +{ + string sourceCode = R"( + contract C { + event E(bytes4, bytes4, uint16, uint8, int16, int8); + function f() { + bytes2 x; assembly { x := 0xf1f2f3f400000000000000000000000000000000000000000000000000000000 } + uint8 a; + uint16 b = 0x1ff; + int8 c; + int16 d; + assembly { a := sub(0, 1) c := 0x0101ff d := 0xff01 } + E(10, x, a, uint8(b), c, int8(d)); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + string(3, 0) + string("\x0a"), string("\xf1\xf2"), + 0xff, 0xff, u256(-1), u256(1) + )); + ) +} + +BOOST_AUTO_TEST_CASE(memory_array_one_dim) +{ + string sourceCode = R"( + contract C { + event E(uint a, int16[] b, uint c); + function f() { + int16[] memory x = new int16[](3); + assembly { + for { let i := 0 } lt(i, 3) { i := add(i, 1) } { + mstore(add(x, mul(add(i, 1), 0x20)), add(0xfffffffe, i)) + } + } + E(10, x, 11); + } + } + )"; + + compileAndRun(sourceCode); + callContractFunction("f()"); + // The old encoder does not clean array elements. + REQUIRE_LOG_DATA(encodeArgs(10, 0x60, 11, 3, u256("0xfffffffe"), u256("0xffffffff"), u256("0x100000000"))); + + compileAndRun(NewEncoderPragma + sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs(10, 0x60, 11, 3, u256(-2), u256(-1), u256(0))); +} + +BOOST_AUTO_TEST_CASE(memory_array_two_dim) +{ + string sourceCode = R"( + contract C { + event E(uint a, int16[][2] b, uint c); + function f() { + int16[][2] memory x; + x[0] = new int16[](3); + x[1] = new int16[](2); + x[0][0] = 7; + x[0][1] = int16(0x010203040506); + x[0][2] = -1; + x[1][0] = 4; + x[1][1] = 5; + E(10, x, 11); + } + } + )"; + NEW_ENCODER( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs(10, 0x60, 11, 0x40, 0xc0, 3, 7, 0x0506, u256(-1), 2, 4, 5)); + ) +} + +BOOST_AUTO_TEST_CASE(memory_byte_array) +{ + string sourceCode = R"( + contract C { + event E(uint a, bytes[] b, uint c); + function f() { + bytes[] memory x = new bytes[](2); + x[0] = "abcabcdefghjklmnopqrsuvwabcdefgijklmnopqrstuwabcdefgijklmnoprstuvw"; + x[1] = "abcdefghijklmnopqrtuvwabcfghijklmnopqstuvwabcdeghijklmopqrstuvw"; + E(10, x, 11); + } + } + )"; + NEW_ENCODER( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + 10, 0x60, 11, + 2, 0x40, 0xc0, + 66, string("abcabcdefghjklmnopqrsuvwabcdefgijklmnopqrstuwabcdefgijklmnoprstuvw"), + 63, string("abcdefghijklmnopqrtuvwabcfghijklmnopqstuvwabcdeghijklmopqrstuvw") + )); + ) +} + +BOOST_AUTO_TEST_CASE(storage_byte_array) +{ + string sourceCode = R"( + contract C { + bytes short; + bytes long; + event E(bytes s, bytes l); + function f() { + short = "123456789012345678901234567890a"; + long = "ffff123456789012345678901234567890afffffffff123456789012345678901234567890a"; + E(short, long); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + 0x40, 0x80, + 31, string("123456789012345678901234567890a"), + 75, string("ffff123456789012345678901234567890afffffffff123456789012345678901234567890a") + )); + ) +} + +BOOST_AUTO_TEST_CASE(storage_array) +{ + string sourceCode = R"( + contract C { + address[3] addr; + event E(address[3] a); + function f() { + assembly { + sstore(0, sub(0, 1)) + sstore(1, sub(0, 2)) + sstore(2, sub(0, 3)) + } + E(addr); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs(u160(-1), u160(-2), u160(-3))); + ) +} + +BOOST_AUTO_TEST_CASE(storage_array_dyn) +{ + string sourceCode = R"( + contract C { + address[] addr; + event E(address[] a); + function f() { + addr.push(1); + addr.push(2); + addr.push(3); + E(addr); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs(0x20, 3, u160(1), u160(2), u160(3))); + ) +} + +BOOST_AUTO_TEST_CASE(storage_array_compact) +{ + string sourceCode = R"( + contract C { + int72[] x; + event E(int72[]); + function f() { + x.push(-1); + x.push(2); + x.push(-3); + x.push(4); + x.push(-5); + x.push(6); + x.push(-7); + x.push(8); + E(x); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f()"); + REQUIRE_LOG_DATA(encodeArgs( + 0x20, 8, u256(-1), 2, u256(-3), 4, u256(-5), 6, u256(-7), 8 + )); + ) +} + +BOOST_AUTO_TEST_CASE(external_function) +{ + string sourceCode = R"( + contract C { + event E(function(uint) external returns (uint), function(uint) external returns (uint)); + function(uint) external returns (uint) g; + function f(uint) returns (uint) { + g = this.f; + E(this.f, g); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f(uint256)"); + string functionIdF = asString(m_contractAddress.ref()) + asString(FixedHash<4>(dev::keccak256("f(uint256)")).ref()); + REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF)); + ) +} + +BOOST_AUTO_TEST_CASE(external_function_cleanup) +{ + string sourceCode = R"( + contract C { + event E(function(uint) external returns (uint), function(uint) external returns (uint)); + // This test relies on the fact that g is stored in slot zero. + function(uint) external returns (uint) g; + function f(uint) returns (uint) { + function(uint) external returns (uint)[1] memory h; + assembly { sstore(0, sub(0, 1)) mstore(h, sub(0, 1)) } + E(h[0], g); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f(uint256)"); + REQUIRE_LOG_DATA(encodeArgs(string(24, char(-1)), string(24, char(-1)))); + ) +} + +BOOST_AUTO_TEST_CASE(calldata) +{ + string sourceCode = R"( + contract C { + event E(bytes); + function f(bytes a) external { + E(a); + } + } + )"; + string s("abcdef"); + string t("abcdefgggggggggggggggggggggggggggggggggggggggghhheeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeggg"); + bool newEncoder = false; + BOTH_ENCODERS( + compileAndRun(sourceCode); + callContractFunction("f(bytes)", 0x20, s.size(), s); + // The old encoder did not pad to multiples of 32 bytes + REQUIRE_LOG_DATA(encodeArgs(0x20, s.size()) + (newEncoder ? encodeArgs(s) : asBytes(s))); + callContractFunction("f(bytes)", 0x20, t.size(), t); + REQUIRE_LOG_DATA(encodeArgs(0x20, t.size()) + (newEncoder ? encodeArgs(t) : asBytes(t))); + newEncoder = true; + ) +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index 00f093b7..03287b28 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -226,18 +226,19 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_with_imports) } )"); BOOST_CHECK(c.compile()); - auto numErrors = c.errors().size(); - // Sometimes we get the prerelease warning, sometimes not. - BOOST_CHECK(2 <= numErrors && numErrors <= 3); + size_t errorCount = 0; for (auto const& e: c.errors()) { string const* msg = e->comment(); BOOST_REQUIRE(msg); + if (msg->find("pre-release") != string::npos) + continue; BOOST_CHECK( - msg->find("pre-release") != string::npos || msg->find("shadows a builtin symbol") != string::npos ); + errorCount++; } + BOOST_CHECK_EQUAL(errorCount, 1); } BOOST_AUTO_TEST_CASE(shadowing_builtins_with_multiple_imports) diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index 0d3caddd..c46e3160 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -38,6 +38,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) // Check that the metadata stamp is at the end of the runtime bytecode. char const* sourceCode = R"( pragma solidity >=0.0; + pragma experimental __testOnlyAnalysis; contract test { function g(function(uint) external returns (uint) x) {} } @@ -58,6 +59,35 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) BOOST_CHECK(std::equal(expectation.begin(), expectation.end(), bytecode.end() - metadataCBORSize - 2)); } +BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) +{ + // Check that the metadata stamp is at the end of the runtime bytecode. + char const* sourceCode = R"( + pragma solidity >=0.0; + pragma experimental __test; + contract test { + function g(function(uint) external returns (uint) x) {} + } + )"; + CompilerStack compilerStack; + compilerStack.addSource("", std::string(sourceCode)); + compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); + ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(), "Compiling contract failed"); + bytes const& bytecode = compilerStack.runtimeObject("test").bytecode; + std::string const& metadata = compilerStack.metadata("test"); + BOOST_CHECK(dev::test::isValidMetadata(metadata)); + bytes hash = dev::swarmHash(metadata).asBytes(); + BOOST_REQUIRE(hash.size() == 32); + BOOST_REQUIRE(bytecode.size() >= 2); + size_t metadataCBORSize = (size_t(bytecode.end()[-2]) << 8) + size_t(bytecode.end()[-1]); + BOOST_REQUIRE(metadataCBORSize < bytecode.size() - 2); + bytes expectation = + bytes{0xa2, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} + + hash + + bytes{0x6c, 'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l', 0xf5}; + BOOST_CHECK(std::equal(expectation.begin(), expectation.end(), bytecode.end() - metadataCBORSize - 2)); +} + BOOST_AUTO_TEST_CASE(metadata_relevant_sources) { CompilerStack compilerStack; diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 452a2662..80b4b6ad 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -76,6 +76,7 @@ BOOST_AUTO_TEST_CASE(basic_test) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -119,6 +120,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -137,6 +139,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) "name": "g", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -169,6 +172,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -207,6 +211,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) "name": "c", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -225,6 +230,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -258,6 +264,7 @@ BOOST_AUTO_TEST_CASE(const_function) "name": "foo", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -280,6 +287,7 @@ BOOST_AUTO_TEST_CASE(const_function) "name": "boo", "constant": true, "payable" : false, + "statemutability": "view", "type": "function", "inputs": [{ "name": "a", @@ -311,6 +319,7 @@ BOOST_AUTO_TEST_CASE(events) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -392,6 +401,7 @@ BOOST_AUTO_TEST_CASE(inherited) "name": "baseFunction", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [{ @@ -408,6 +418,7 @@ BOOST_AUTO_TEST_CASE(inherited) "name": "derivedFunction", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [{ @@ -463,6 +474,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -505,6 +517,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) "name": "f", "constant": false, "payable" : false, + "statemutability": "nonpayable", "type": "function", "inputs": [ { @@ -548,12 +561,44 @@ BOOST_AUTO_TEST_CASE(constructor_abi) } ], "payable": false, + "statemutability": "nonpayable", "type": "constructor" } ])"; checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(payable_constructor_abi) +{ + char const* sourceCode = R"( + contract test { + function test(uint param1, test param2, bool param3) payable {} + } + )"; + + char const* interface = R"([ + { + "inputs": [ + { + "name": "param1", + "type": "uint256" + }, + { + "name": "param2", + "type": "address" + }, + { + "name": "param3", + "type": "bool" + } + ], + "payable": true, + "statemutability": "payable", + "type": "constructor" + } + ])"; + checkInterface(sourceCode, interface); +} BOOST_AUTO_TEST_CASE(return_param_in_abi) { @@ -574,6 +619,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "inputs" : [], "name" : "ret", "outputs" : [ @@ -592,6 +638,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) } ], "payable": false, + "statemutability": "nonpayable", "type": "constructor" } ] @@ -613,6 +660,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "name": "f", "inputs": [ { "name": "a", "type": "string" }, @@ -641,6 +689,7 @@ BOOST_AUTO_TEST_CASE(library_function) { "constant" : false, "payable" : false, + "statemutability": "nonpayable", "name": "f", "inputs": [ { "name": "b", "type": "test.StructType storage" }, @@ -670,6 +719,7 @@ BOOST_AUTO_TEST_CASE(include_fallback_function) [ { "payable": false, + "statemutability": "nonpayable", "type" : "fallback" } ] @@ -691,6 +741,7 @@ BOOST_AUTO_TEST_CASE(payable_function) { "constant" : false, "payable": false, + "statemutability": "nonpayable", "inputs": [], "name": "f", "outputs": [], @@ -699,6 +750,7 @@ BOOST_AUTO_TEST_CASE(payable_function) { "constant" : false, "payable": true, + "statemutability": "payable", "inputs": [], "name": "g", "outputs": [], @@ -721,6 +773,7 @@ BOOST_AUTO_TEST_CASE(payable_fallback_function) [ { "payable": true, + "statemutability": "payable", "type" : "fallback" } ] @@ -741,6 +794,7 @@ BOOST_AUTO_TEST_CASE(function_type) { "constant" : false, "payable": false, + "statemutability": "nonpayable", "inputs": [{ "name": "x", "type": "function" diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 5bcde441..73dd7d22 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1950,6 +1950,87 @@ BOOST_AUTO_TEST_CASE(ripemd) testContractAgainstCpp("a(bytes32)", f, u256(-1)); } +BOOST_AUTO_TEST_CASE(packed_keccak256) +{ + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 hash) { + var b = 65536; + uint c = 256; + return keccak256(8, input, b, input, c); + } + } + )"; + compileAndRun(sourceCode); + auto f = [&](u256 const& _x) -> u256 + { + return dev::keccak256( + toCompactBigEndian(unsigned(8)) + + toBigEndian(_x) + + toCompactBigEndian(unsigned(65536)) + + toBigEndian(_x) + + toBigEndian(u256(256)) + ); + }; + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); +} + +BOOST_AUTO_TEST_CASE(packed_sha256) +{ + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 hash) { + var b = 65536; + uint c = 256; + return sha256(8, input, b, input, c); + } + } + )"; + compileAndRun(sourceCode); + auto f = [&](u256 const& _x) -> bytes + { + if (_x == u256(4)) + return fromHex("804e0d7003cfd70fc925dc103174d9f898ebb142ecc2a286da1abd22ac2ce3ac"); + if (_x == u256(5)) + return fromHex("e94921945f9068726c529a290a954f412bcac53184bb41224208a31edbf63cf0"); + if (_x == u256(-1)) + return fromHex("f14def4d07cd185ddd8b10a81b2238326196a38867e6e6adbcc956dc913488c7"); + return fromHex(""); + }; + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); +} + +BOOST_AUTO_TEST_CASE(packed_ripemd160) +{ + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 hash) { + var b = 65536; + uint c = 256; + return ripemd160(8, input, b, input, c); + } + } + )"; + compileAndRun(sourceCode); + auto f = [&](u256 const& _x) -> bytes + { + if (_x == u256(4)) + return fromHex("f93175303eba2a7b372174fc9330237f5ad202fc000000000000000000000000"); + if (_x == u256(5)) + return fromHex("04f4fc112e2bfbe0d38f896a46629e08e2fcfad5000000000000000000000000"); + if (_x == u256(-1)) + return fromHex("c0a2e4b1f3ff766a9a0089e7a410391730872495000000000000000000000000"); + return fromHex(""); + }; + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); +} + BOOST_AUTO_TEST_CASE(ecrecover) { char const* sourceCode = R"( @@ -2318,21 +2399,6 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5)); } -BOOST_AUTO_TEST_CASE(gas_for_builtin) -{ - char const* sourceCode = R"( - contract Contract { - function test(uint g) returns (bytes32 data, bool flag) { - data = ripemd160.gas(g)("abc"); - flag = true; - } - } - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test(uint256)", 500) == bytes()); - BOOST_CHECK(callContractFunction("test(uint256)", 800) == encodeArgs(u256("0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc000000000000000000000000"), true)); -} - BOOST_AUTO_TEST_CASE(value_complex) { char const* sourceCode = R"( @@ -3062,7 +3128,7 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data) 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, 4) + FixedHash<4>(dev::keccak256("deposit()")).asBytes()); + BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4) + FixedHash<4>(dev::keccak256("deposit()")).asBytes())); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); } @@ -3086,7 +3152,32 @@ 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, string("ABC"))); + BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(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::keccak256(string("Deposit(uint256,bytes,uint256)"))); +} + +BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage) +{ + char const* sourceCode = R"( + contract ClientReceipt { + bytes x; + event Deposit(uint fixeda, bytes dynx, uint fixedb); + function deposit() { + x.length = 31; + x[0] = "A"; + x[1] = "B"; + x[2] = "C"; + x[30] = "Z"; + Deposit(10, x, 15); + } + } + )"; + compileAndRun(sourceCode); + 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, 31, string("ABC") + string(27, 0) + "Z")); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); } @@ -4336,6 +4427,92 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) BOOST_CHECK(storageEmpty(m_contractAddress)); } +BOOST_AUTO_TEST_CASE(array_copy_storage_abi) +{ + // NOTE: This does not really test copying from storage to ABI directly, + // because it will always copy to memory first. + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract c { + uint8[] x; + uint16[] y; + uint24[] z; + uint24[][] w; + function test1() returns (uint8[]) { + for (uint i = 0; i < 101; ++i) + x.push(uint8(i)); + return x; + } + function test2() returns (uint16[]) { + for (uint i = 0; i < 101; ++i) + y.push(uint16(i)); + return y; + } + function test3() returns (uint24[]) { + for (uint i = 0; i < 101; ++i) + z.push(uint24(i)); + return z; + } + function test4() returns (uint24[][]) { + w.length = 5; + for (uint i = 0; i < 5; ++i) + for (uint j = 0; j < 101; ++j) + w[i].push(uint24(j)); + return w; + } + } + )"; + compileAndRun(sourceCode); + bytes valueSequence; + for (size_t i = 0; i < 101; ++i) + valueSequence += toBigEndian(u256(i)); + BOOST_CHECK(callContractFunction("test1()") == encodeArgs(0x20, 101) + valueSequence); + BOOST_CHECK(callContractFunction("test2()") == encodeArgs(0x20, 101) + valueSequence); + BOOST_CHECK(callContractFunction("test3()") == encodeArgs(0x20, 101) + valueSequence); + BOOST_CHECK(callContractFunction("test4()") == + encodeArgs(0x20, 5, 0xa0, 0xa0 + 102 * 32 * 1, 0xa0 + 102 * 32 * 2, 0xa0 + 102 * 32 * 3, 0xa0 + 102 * 32 * 4) + + encodeArgs(101) + valueSequence + + encodeArgs(101) + valueSequence + + encodeArgs(101) + valueSequence + + encodeArgs(101) + valueSequence + + encodeArgs(101) + valueSequence + ); +} + +BOOST_AUTO_TEST_CASE(array_copy_storage_abi_signed) +{ + // NOTE: This does not really test copying from storage to ABI directly, + // because it will always copy to memory first. + char const* sourceCode = R"( + contract c { + int16[] x; + function test() returns (int16[]) { + x.push(int16(-1)); + x.push(int16(-1)); + x.push(int16(8)); + x.push(int16(-16)); + x.push(int16(-2)); + x.push(int16(6)); + x.push(int16(8)); + x.push(int16(-1)); + return x; + } + } + )"; + compileAndRun(sourceCode); + bytes valueSequence; + BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x20, 8, + u256(-1), + u256(-1), + u256(8), + u256(-16), + u256(-2), + u256(6), + u256(8), + u256(-1) + )); +} + BOOST_AUTO_TEST_CASE(array_push) { char const* sourceCode = R"( @@ -8251,6 +8428,53 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); } +BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) +{ + char const* sourceCode = R"( + contract C { + function f() returns (address) { + return recover( + 0x77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca, + 0, // invalid v value + 0x6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4, + 0xef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d, + 0xca35b7d915458ef540ade6068dfe2f44e8fa733c, + 0xca35b7d915458ef540ade6068dfe2f44e8fa733c + ); + } + function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s, uint blockExpired, bytes32 salt) + returns (address) + { + require(hash == keccak256(blockExpired, salt)); + return ecrecover(hash, v, r, s); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) +{ + char const* sourceCode = R"( + contract C { + function f() returns (address) { + assembly { + mstore(mload(0x40), 0xca35b7d915458ef540ade6068dfe2f44e8fa733c) + } + return ecrecover( + 0x77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca, + 0, // invalid v value + 0x6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4, + 0xef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d + ); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); +} + BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) { char const* sourceCode = R"( @@ -9769,6 +9993,64 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0), u256(0))); } +BOOST_AUTO_TEST_CASE(bare_call_invalid_address) +{ + char const* sourceCode = R"( + contract C { + /// Calling into non-existant account is successful (creates the account) + function f() external constant returns (bool) { + return address(0x4242).call(); + } + function g() external constant returns (bool) { + return address(0x4242).callcode(); + } + function h() external constant returns (bool) { + return address(0x4242).delegatecall(); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(1))); +} + +BOOST_AUTO_TEST_CASE(delegatecall_return_value) +{ + char const* sourceCode = R"DELIMITER( + contract C { + uint value; + function set(uint _value) external { + value = _value; + } + function get() external constant returns (uint) { + return value; + } + function get_delegated() external constant returns (bool) { + return this.delegatecall(bytes4(sha3("get()"))); + } + function assert0() external constant { + assert(value == 0); + } + function assert0_delegated() external constant returns (bool) { + return this.delegatecall(bytes4(sha3("assert0()"))); + } + } + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("set(uint256)", u256(1)) == encodeArgs()); + BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("set(uint256)", u256(42)) == encodeArgs()); + BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(42))); + BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index cd922cc8..51d60596 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -249,7 +249,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) uint128 variable; } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(double_function_declaration) @@ -260,7 +260,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) function fun() { } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Function with same name and arguments defined twice."); } BOOST_AUTO_TEST_CASE(double_variable_declaration) @@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration) } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(name_shadowing) @@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); } BOOST_AUTO_TEST_CASE(reference_to_later_declaration) @@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Recursive struct definition."); } BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Recursive struct definition."); } BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) @@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) function f() returns (bool r1, bool r2) { return 1 >= 2; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Different number of arguments in return statement than in returns declaration."); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) @@ -416,7 +416,7 @@ BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) function f() returns (uint256 r) { return 1 >= 2; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Return argument type bool is not implicitly convertible to expected type (type of first return variable) uint256."); } BOOST_AUTO_TEST_CASE(type_checking_function_call) @@ -447,7 +447,7 @@ BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) function f() { int32(2) == uint64(2); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Operator == not compatible with types int32 and uint64"); } BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) @@ -491,7 +491,7 @@ BOOST_AUTO_TEST_CASE(balance_invalid) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(assignment_to_mapping) @@ -508,7 +508,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_mapping) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Mappings cannot be assigned to."); } BOOST_AUTO_TEST_CASE(assignment_to_struct) @@ -535,7 +535,7 @@ BOOST_AUTO_TEST_CASE(returns_in_constructor) function test() returns (uint a) { } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Non-empty \"returns\" directive for constructor."); } BOOST_AUTO_TEST_CASE(forward_function_reference) @@ -624,7 +624,7 @@ BOOST_AUTO_TEST_CASE(function_no_implementation) std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get()); BOOST_REQUIRE(contract); - BOOST_CHECK(!contract->annotation().isFullyImplemented); + BOOST_CHECK(!contract->annotation().unimplementedFunctions.empty()); BOOST_CHECK(!contract->definedFunctions()[0]->isImplemented()); } @@ -640,10 +640,10 @@ BOOST_AUTO_TEST_CASE(abstract_contract) ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get()); ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get()); BOOST_REQUIRE(base); - BOOST_CHECK(!base->annotation().isFullyImplemented); + BOOST_CHECK(!base->annotation().unimplementedFunctions.empty()); BOOST_CHECK(!base->definedFunctions()[0]->isImplemented()); BOOST_REQUIRE(derived); - BOOST_CHECK(derived->annotation().isFullyImplemented); + BOOST_CHECK(derived->annotation().unimplementedFunctions.empty()); BOOST_CHECK(derived->definedFunctions()[0]->isImplemented()); } @@ -659,9 +659,9 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get()); ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get()); BOOST_REQUIRE(base); - BOOST_CHECK(!base->annotation().isFullyImplemented); + BOOST_CHECK(!base->annotation().unimplementedFunctions.empty()); BOOST_REQUIRE(derived); - BOOST_CHECK(!derived->annotation().isFullyImplemented); + BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty()); } BOOST_AUTO_TEST_CASE(create_abstract_contract) @@ -674,45 +674,7 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) function foo() { b = new base(); } } )"; - CHECK_ERROR(text, TypeError, ""); -} - -BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) -{ - ASTPointer<SourceUnit> sourceUnit; - char const* text = R"( - contract BaseBase { function BaseBase(uint j); } - contract base is BaseBase { function foo(); } - contract derived is base { - function derived(uint i) BaseBase(i){} - function foo() {} - } - )"; - ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed"); - std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); - BOOST_CHECK_EQUAL(nodes.size(), 4); - ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[3].get()); - BOOST_REQUIRE(derived); - BOOST_CHECK(!derived->annotation().isFullyImplemented); -} - -BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided) -{ - ASTPointer<SourceUnit> sourceUnit; - char const* text = R"( - contract BaseBase { function BaseBase(uint); } - contract base is BaseBase { function foo(); } - contract derived is base { - function derived(uint) {} - function foo() {} - } - )"; - ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed"); - std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); - BOOST_CHECK_EQUAL(nodes.size(), 4); - ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[3].get()); - BOOST_REQUIRE(derived); - BOOST_CHECK(!derived->annotation().isFullyImplemented); + CHECK_ERROR(text, TypeError, "Trying to create an instance of an abstract contract."); } BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) @@ -723,7 +685,7 @@ BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) contract derived is base { function foo() {} } contract wrong is derived { function foo(); } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Redeclaring an already implemented function as abstract"); } BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) @@ -738,7 +700,7 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) BOOST_CHECK_EQUAL(nodes.size(), 3); ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get()); BOOST_REQUIRE(derived); - BOOST_CHECK(!derived->annotation().isFullyImplemented); + BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty()); } BOOST_AUTO_TEST_CASE(function_canonical_signature) @@ -855,7 +817,7 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) function g (C c) external {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested."); } BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) @@ -889,7 +851,7 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from address to contract C requested."); } BOOST_AUTO_TEST_CASE(hash_collision_in_interface) @@ -900,7 +862,7 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface) function tgeo() { } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Function signature hash collision for tgeo()"); } BOOST_AUTO_TEST_CASE(inheritance_basic) @@ -934,7 +896,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) contract A is B { } contract B is A { } )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Definition of base has to precede definition of derived contract"); } BOOST_AUTO_TEST_CASE(legal_override_direct) @@ -962,16 +924,25 @@ BOOST_AUTO_TEST_CASE(illegal_override_visibility) contract B { function f() internal {} } contract C is B { function f() public {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Overriding function visibility differs"); } -BOOST_AUTO_TEST_CASE(illegal_override_constness) +BOOST_AUTO_TEST_CASE(illegal_override_remove_constness) { char const* text = R"( contract B { function f() constant {} } contract C is B { function f() {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Overriding function should be declared constant."); +} + +BOOST_AUTO_TEST_CASE(illegal_override_add_constness) +{ + char const* text = R"( + contract B { function f() {} } + contract C is B { function f() constant {} } + )"; + CHECK_ERROR(text, TypeError, "Overriding function should not be declared constant."); } BOOST_AUTO_TEST_CASE(complex_inheritance) @@ -1041,7 +1012,7 @@ BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) function f() { B b = A(1); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type contract A is not implicitly convertible to expected type contract B."); } BOOST_AUTO_TEST_CASE(super_excludes_current_contract) @@ -1058,7 +1029,7 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract) } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract super B"); } BOOST_AUTO_TEST_CASE(function_modifier_invocation) @@ -1081,7 +1052,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) modifier mod1(uint a) { if (a > 0) _; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid type for argument in modifier invocation. Invalid implicit conversion from bool to uint256 requested."); } BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) @@ -1144,7 +1115,7 @@ BOOST_AUTO_TEST_CASE(illegal_modifier_override) contract A { modifier mod(uint a) { _; } } contract B is A { modifier mod(uint8 a) { _; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Override changes modifier signature."); } BOOST_AUTO_TEST_CASE(modifier_overrides_function) @@ -1155,7 +1126,7 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function) )"; // Error: Identifier already declared. // Error: Override changes modifier to function. - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Identifier already declared"); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -1166,7 +1137,7 @@ BOOST_AUTO_TEST_CASE(function_overrides_modifier) )"; // Error: Identifier already declared. // Error: Override changes function to modifier. - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(modifier_returns_value) @@ -1232,7 +1203,7 @@ BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) function foo() {} } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(private_state_variable) @@ -1267,7 +1238,7 @@ BOOST_AUTO_TEST_CASE(missing_state_variable) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"stateVar\" not found or not visible after argument-dependent lookup in type(contract Scope)"); } @@ -1293,7 +1264,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) Data public data; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Internal type is not allowed for public state variables."); } BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) @@ -1322,7 +1293,7 @@ BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1) function foo() returns (uint256) { return Parent2.m_aMember1; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"m_aMember1\" not found or not visible after argument-dependent lookup in type(contract Parent2)"); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) @@ -1339,7 +1310,7 @@ BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) uint256 public m_aMember3; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"m_aMember2\" not found or not visible after argument-dependent lookup in type(contract Child)"); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -1361,7 +1332,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) function(uint a) { x = 2; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Fallback function cannot take parameters."); } BOOST_AUTO_TEST_CASE(fallback_function_in_library) @@ -1371,7 +1342,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_in_library) function() {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Libraries cannot have fallback functions."); } BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) @@ -1381,7 +1352,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) function() returns (uint) { } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Fallback function cannot return values."); } BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) @@ -1392,7 +1363,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) function() constant { x = 2; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Fallback function cannot be declared constant."); } BOOST_AUTO_TEST_CASE(fallback_function_twice) @@ -1404,7 +1375,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice) function() { x = 3; } } )"; - CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "Function with same name and arguments defined twice."); } BOOST_AUTO_TEST_CASE(fallback_function_inheritance) @@ -1439,7 +1410,7 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed) event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "More than 3 indexed arguments for event."); } BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) @@ -1459,7 +1430,7 @@ BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed) event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "More than 4 indexed arguments for anonymous event."); } BOOST_AUTO_TEST_CASE(events_with_same_name) @@ -1578,7 +1549,7 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function) function g() { c(0).f(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract c"); } BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) @@ -1591,7 +1562,7 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) function g() { c(0).a(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"a\" not found or not visible after argument-dependent lookup in contract c"); } BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) @@ -1619,7 +1590,7 @@ BOOST_AUTO_TEST_CASE(error_count_in_named_args) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Wrong argument count for function call: 1 arguments given but expected 2."); } BOOST_AUTO_TEST_CASE(empty_in_named_args) @@ -1634,7 +1605,7 @@ BOOST_AUTO_TEST_CASE(empty_in_named_args) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Wrong argument count for function call: 0 arguments given but expected 2."); } BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) @@ -1649,7 +1620,7 @@ BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Duplicate named argument."); } BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) @@ -1664,7 +1635,7 @@ BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Named argument does not match function declaration."); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter) @@ -1718,7 +1689,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Different number of arguments in return statement than in returns declaration."); } BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) @@ -1728,7 +1699,7 @@ BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) function f() { var (x) = f(); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Not enough components (0) in value to assign all variables (1)."); } BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) @@ -1751,7 +1722,7 @@ BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) uint256 a; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type int_const 115792089237316195423570985008687907853269984665640564039458000000000000000000 is not implicitly convertible to expected type uint256."); } BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) @@ -1761,7 +1732,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) function f() returns(uint d) { return 2 ** 10000000000; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Operator ** not compatible with types int_const 2 and int_const 10000000000"); } BOOST_AUTO_TEST_CASE(exp_warn_literal_base) @@ -1875,7 +1846,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access) ActionChoices choices; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"RunAroundWavingYourHands\" not found or not visible after argument-dependent lookup in type(enum test.ActionChoices)"); } BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) @@ -1889,7 +1860,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) ActionChoices choices; } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); } BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) @@ -1935,7 +1906,7 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_256) uint256 a; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type enum test.ActionChoices is not implicitly convertible to expected type uint256."); } BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64) @@ -1949,7 +1920,7 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64) uint64 b; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type enum test.ActionChoices is not implicitly convertible to expected type uint64."); } BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) @@ -1963,7 +1934,7 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed from \"enum test.Paper\" to \"enum test.Ground\"."); } BOOST_AUTO_TEST_CASE(enum_duplicate_values) @@ -1973,7 +1944,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) @@ -2003,7 +1974,7 @@ BOOST_AUTO_TEST_CASE(private_visibility) function g() { f(); } } )"; - CHECK_ERROR(sourceCode, DeclarationError, ""); + CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); } BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) @@ -2016,7 +1987,7 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) function g() { base.f(); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in type(contract base)"); } BOOST_AUTO_TEST_CASE(external_visibility) @@ -2027,7 +1998,7 @@ BOOST_AUTO_TEST_CASE(external_visibility) function g() { f(); } } )"; - CHECK_ERROR(sourceCode, DeclarationError, ""); + CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); } BOOST_AUTO_TEST_CASE(external_base_visibility) @@ -2040,7 +2011,7 @@ BOOST_AUTO_TEST_CASE(external_base_visibility) function g() { base.f(); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in type(contract base)"); } BOOST_AUTO_TEST_CASE(external_argument_assign) @@ -2050,7 +2021,7 @@ BOOST_AUTO_TEST_CASE(external_argument_assign) function f(uint a) external { a = 1; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(external_argument_increment) @@ -2060,7 +2031,7 @@ BOOST_AUTO_TEST_CASE(external_argument_increment) function f(uint a) external { a++; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(external_argument_delete) @@ -2070,7 +2041,7 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) function f(uint a) external { delete a; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) @@ -2093,7 +2064,7 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) function f(uint a) { uint8[a] x; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); } BOOST_AUTO_TEST_CASE(array_with_negative_length) @@ -2115,7 +2086,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) function f() { b = a; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type bytes storage ref is not implicitly convertible to expected type uint256[] storage ref."); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) @@ -2127,7 +2098,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) function f() { b = a; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type uint32[] storage ref is not implicitly convertible to expected type uint8[] storage ref."); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) @@ -2163,7 +2134,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) function f() { b = a; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type uint256[] storage ref is not implicitly convertible to expected type uint256[80] storage ref."); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) @@ -2173,7 +2144,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) uint8 a = 1000; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type int_const 1000 is not implicitly convertible to expected type uint8."); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) @@ -2183,7 +2154,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) uint a = "abc"; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type uint256."); } BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) @@ -2344,7 +2315,7 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) uint constant x = 56; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); } BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) @@ -2454,7 +2425,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable) uint constant y; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Uninitialized \"constant\" variable."); } BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) @@ -2466,7 +2437,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) function g() returns(uint) { return f(3, 5); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "No matching declaration found after argument-dependent lookup."); } BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) @@ -2479,7 +2450,7 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) function g() returns(uint) { return f(1); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "No unique declaration found after argument-dependent lookup."); } BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function) @@ -2502,7 +2473,7 @@ BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function) function g() returns(uint) { var x = f; return x(7); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "No matching declaration found after variable lookup."); } BOOST_AUTO_TEST_CASE(external_types_clash) @@ -2516,7 +2487,7 @@ BOOST_AUTO_TEST_CASE(external_types_clash) function f(uint8 a) { } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Function overload clash during conversion to external types for arguments."); } BOOST_AUTO_TEST_CASE(override_changes_return_types) @@ -2529,7 +2500,7 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types) function f(uint a) returns (uint8) { } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Overriding function return types differ"); } BOOST_AUTO_TEST_CASE(multiple_constructors) @@ -2540,7 +2511,7 @@ BOOST_AUTO_TEST_CASE(multiple_constructors) function test() {} } )"; - CHECK_ERROR(sourceCode, DeclarationError, ""); + CHECK_ERROR(sourceCode, DeclarationError, "More than one constructor defined"); } BOOST_AUTO_TEST_CASE(equal_overload) @@ -2551,7 +2522,7 @@ BOOST_AUTO_TEST_CASE(equal_overload) function test(uint a) external {} } )"; - CHECK_ERROR_ALLOW_MULTI(sourceCode, DeclarationError, ""); + CHECK_ERROR_ALLOW_MULTI(sourceCode, DeclarationError, "Function with same name and arguments defined twice."); } BOOST_AUTO_TEST_CASE(uninitialized_var) @@ -2561,7 +2532,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) function f() returns (uint) { var x; return 2; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Assignment necessary for type detection."); } BOOST_AUTO_TEST_CASE(string) @@ -2613,7 +2584,7 @@ BOOST_AUTO_TEST_CASE(string_index) function f() { var a = s[2]; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Index access for string is not possible."); } BOOST_AUTO_TEST_CASE(string_length) @@ -2624,7 +2595,7 @@ BOOST_AUTO_TEST_CASE(string_length) function f() { var a = s.length; } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Member \"length\" not found or not visible after argument-dependent lookup in string storage ref"); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) @@ -2634,7 +2605,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) int8 public i = -129; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type int_const -129 is not implicitly convertible to expected type int8."); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min) @@ -2654,7 +2625,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound) int8 public j = 128; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type int_const 128 is not implicitly convertible to expected type int8."); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max) @@ -2674,7 +2645,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned) uint8 public x = -1; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type int_const -1 is not implicitly convertible to expected type uint8."); } BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) @@ -2684,7 +2655,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) uint8 public x = 700; } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type int_const 700 is not implicitly convertible to expected type uint8."); } BOOST_AUTO_TEST_CASE(integer_boolean_operators) @@ -2692,15 +2663,15 @@ BOOST_AUTO_TEST_CASE(integer_boolean_operators) char const* sourceCode1 = R"( contract test { function() { uint x = 1; uint y = 2; x || y; } } )"; - CHECK_ERROR(sourceCode1, TypeError, ""); + CHECK_ERROR(sourceCode1, TypeError, "Operator || not compatible with types uint256 and uint256"); char const* sourceCode2 = R"( contract test { function() { uint x = 1; uint y = 2; x && y; } } )"; - CHECK_ERROR(sourceCode2, TypeError, ""); + CHECK_ERROR(sourceCode2, TypeError, "Operator && not compatible with types uint256 and uint256"); char const* sourceCode3 = R"( contract test { function() { uint x = 1; !x; } } )"; - CHECK_ERROR(sourceCode3, TypeError, ""); + CHECK_ERROR(sourceCode3, TypeError, "Unary operator ! cannot be applied to type uint256"); } BOOST_AUTO_TEST_CASE(exp_signed_variable) @@ -2708,15 +2679,15 @@ BOOST_AUTO_TEST_CASE(exp_signed_variable) char const* sourceCode1 = R"( contract test { function() { uint x = 3; int y = -4; x ** y; } } )"; - CHECK_ERROR(sourceCode1, TypeError, ""); + CHECK_ERROR(sourceCode1, TypeError, "Operator ** not compatible with types uint256 and int256"); char const* sourceCode2 = R"( contract test { function() { uint x = 3; int y = -4; y ** x; } } )"; - CHECK_ERROR(sourceCode2, TypeError, ""); + CHECK_ERROR(sourceCode2, TypeError, "Operator ** not compatible with types int256 and uint256"); char const* sourceCode3 = R"( contract test { function() { int x = -3; int y = -4; x ** y; } } )"; - CHECK_ERROR(sourceCode3, TypeError, ""); + CHECK_ERROR(sourceCode3, TypeError, "Operator ** not compatible with types int256 and int256"); } BOOST_AUTO_TEST_CASE(reference_compare_operators) @@ -2724,11 +2695,11 @@ BOOST_AUTO_TEST_CASE(reference_compare_operators) char const* sourceCode1 = R"( contract test { bytes a; bytes b; function() { a == b; } } )"; - CHECK_ERROR(sourceCode1, TypeError, ""); + CHECK_ERROR(sourceCode1, TypeError, "Operator == not compatible with types bytes storage ref and bytes storage ref"); char const* sourceCode2 = R"( contract test { struct s {uint a;} s x; s y; function() { x == y; } } )"; - CHECK_ERROR(sourceCode2, TypeError, ""); + CHECK_ERROR(sourceCode2, TypeError, "Operator == not compatible with types struct test.s storage ref and struct test.s storage ref"); } BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) @@ -2738,7 +2709,7 @@ BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) function f(uint[] memory a) external {} } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Location has to be calldata for external functions (remove the \"memory\" or \"storage\" keyword)."); } BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) @@ -2748,7 +2719,7 @@ BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) function f(uint[] storage a) external {} } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Location has to be calldata for external functions (remove the \"memory\" or \"storage\" keyword)."); } BOOST_AUTO_TEST_CASE(storage_location_local_variables) @@ -2775,7 +2746,7 @@ BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type mapping(uint256 => uint256)[] memory is only valid in storage."); } BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) @@ -2789,7 +2760,7 @@ BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type uint256[] memory is not implicitly convertible to expected type uint256[] storage pointer."); } BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) @@ -2806,7 +2777,7 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type uint8[] storage pointer is not implicitly convertible to expected type uint256[] storage pointer."); } BOOST_AUTO_TEST_CASE(uninitialized_mapping_variable) @@ -2846,7 +2817,7 @@ BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Unary operator delete cannot be applied to type uint256[] storage pointer"); } BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) @@ -2873,7 +2844,7 @@ BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Invalid type for argument in function call. Invalid implicit conversion from uint256[] memory to uint256[] storage pointer requested."); } BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) @@ -2902,7 +2873,7 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Type uint8[] memory is not implicitly convertible to expected type uint256[] memory."); } BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) @@ -2917,7 +2888,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed from \"inaccessible dynamic type\" to \"bytes storage pointer\"."); } BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) @@ -2930,7 +2901,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(struct_constructor) @@ -3000,7 +2971,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"b\" is not available in struct Test.S memory outside of storage."); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -3026,7 +2997,7 @@ BOOST_AUTO_TEST_CASE(inheriting_from_library) library Lib {} contract Test is Lib {} )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Libraries cannot be inherited from."); } BOOST_AUTO_TEST_CASE(inheriting_library) @@ -3035,7 +3006,7 @@ BOOST_AUTO_TEST_CASE(inheriting_library) contract Test {} library Lib is Test {} )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Library is not allowed to inherit."); } BOOST_AUTO_TEST_CASE(library_having_variables) @@ -3043,7 +3014,7 @@ BOOST_AUTO_TEST_CASE(library_having_variables) char const* text = R"( library Lib { uint x; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables"); } BOOST_AUTO_TEST_CASE(valid_library) @@ -3076,7 +3047,7 @@ BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) function f() { var x = new Test(); } } )"; - CHECK_ERROR(sourceCode, TypeError, ""); + CHECK_ERROR(sourceCode, TypeError, "Circular reference for contract creation (cannot create instance of derived or same contract)."); } BOOST_AUTO_TEST_CASE(array_out_of_bound_access) @@ -3090,7 +3061,7 @@ BOOST_AUTO_TEST_CASE(array_out_of_bound_access) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Out of bounds array access."); } BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) @@ -3100,7 +3071,7 @@ BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) function f() { string x = "abc"; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type literal_string \"abc\" is not implicitly convertible to expected type string storage pointer."); } BOOST_AUTO_TEST_CASE(non_initialized_references) @@ -3130,7 +3101,7 @@ BOOST_AUTO_TEST_CASE(keccak256_with_large_integer_constant) function f() { keccak256(2**500); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid rational number (too large or division by zero)."); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) @@ -3140,7 +3111,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) contract B { function f() { new C(); } } contract C { function f() { new A(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Circular reference for contract creation (cannot create instance of derived or same contract)."); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) @@ -3150,7 +3121,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) contract B { function f() { new C(); } } contract C { function f() { new A(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Definition of base has to precede definition of derived contract"); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) @@ -3190,7 +3161,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) function f() { var (a, b, ) = one(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) { @@ -3200,7 +3171,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) function f() { var (a, , ) = one(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) @@ -3211,7 +3182,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) function f() { var (, , a) = one(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) @@ -3222,7 +3193,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) function f() { var (, a, b) = one(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Not enough components (1) in value to assign all variables (2)."); } BOOST_AUTO_TEST_CASE(tuples) @@ -3250,7 +3221,7 @@ BOOST_AUTO_TEST_CASE(tuples_empty_components) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Tuple component cannot be empty."); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) @@ -3261,7 +3232,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) function f() { var (,) = one(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Wildcard both at beginning and end of variable declaration list is only allowed if the number of components is equal."); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) @@ -3272,7 +3243,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) function f() { var (a, b, c) = two(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Not enough components (2) in value to assign all variables (3)"); } BOOST_AUTO_TEST_CASE(tuple_assignment_from_void_function) @@ -3340,7 +3311,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_library) using D for uint; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Library name expected."); } BOOST_AUTO_TEST_CASE(using_for_function_exists) @@ -3431,7 +3402,7 @@ BOOST_AUTO_TEST_CASE(using_for_mismatch) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint256"); } BOOST_AUTO_TEST_CASE(using_for_not_used) @@ -3447,7 +3418,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_used) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint16"); } BOOST_AUTO_TEST_CASE(library_memory_struct) @@ -3458,7 +3429,7 @@ BOOST_AUTO_TEST_CASE(library_memory_struct) function f() returns (S ) {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type is not allowed for public or external functions."); } BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) @@ -3473,7 +3444,7 @@ BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"double\" not found or not visible after argument-dependent lookup in uint256"); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -3520,7 +3491,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_memory_array) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Type cannot live outside storage."); } BOOST_AUTO_TEST_CASE(new_for_non_array) @@ -3532,7 +3503,7 @@ BOOST_AUTO_TEST_CASE(new_for_non_array) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Contract or array type expected."); } BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) @@ -3544,7 +3515,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Wrong argument count for function call: 0 arguments given but expected 1."); } BOOST_AUTO_TEST_CASE(function_overload_array_type) @@ -3664,7 +3635,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Unable to deduce common type for array elements."); } BOOST_AUTO_TEST_CASE(dynamic_inline_array) @@ -3689,7 +3660,7 @@ BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Inline array type cannot be declared as LValue."); } BOOST_AUTO_TEST_CASE(break_not_in_loop) @@ -3702,7 +3673,7 @@ BOOST_AUTO_TEST_CASE(break_not_in_loop) } } )"; - CHECK_ERROR(text, SyntaxError, ""); + CHECK_ERROR(text, SyntaxError, "\"break\" has to be in a \"for\" or \"while\" loop."); } BOOST_AUTO_TEST_CASE(continue_not_in_loop) @@ -3715,7 +3686,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop) } } )"; - CHECK_ERROR(text, SyntaxError, ""); + CHECK_ERROR(text, SyntaxError, "\"continue\" has to be in a \"for\" or \"while\" loop."); } BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) @@ -3730,7 +3701,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) } } )"; - CHECK_ERROR(text, SyntaxError, ""); + CHECK_ERROR(text, SyntaxError, "\"continue\" has to be in a \"for\" or \"while\" loop."); } BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) @@ -3742,7 +3713,7 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "True expression's type bool doesn't match false expression's type uint8."); } BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) @@ -3756,7 +3727,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) } } )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Conditional expression as left value is not supported yet."); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) @@ -3776,7 +3747,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "True expression's type struct C.s1 memory doesn't match false expression's type struct C.s2 memory."); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) @@ -3791,7 +3762,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "True expression's type function (bool) doesn't match false expression's type function ()."); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) @@ -3809,7 +3780,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "True expression's type enum C.small doesn't match false expression's type enum C.big."); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) @@ -3824,7 +3795,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "True expression's type mapping(uint8 => uint8) doesn't match false expression's type mapping(uint32 => uint8)."); } BOOST_AUTO_TEST_CASE(conditional_with_all_types) @@ -3931,7 +3902,7 @@ BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Wrong argument count for modifier invocation: 1 arguments given but expected 0."); } BOOST_AUTO_TEST_CASE(index_access_for_bytes) @@ -4721,7 +4692,7 @@ BOOST_AUTO_TEST_CASE(modifier_without_underscore) modifier m() {} } )"; - CHECK_ERROR(text, SyntaxError, ""); + CHECK_ERROR(text, SyntaxError, "Modifier body does not contain '_'."); } BOOST_AUTO_TEST_CASE(payable_in_library) @@ -4731,7 +4702,7 @@ BOOST_AUTO_TEST_CASE(payable_in_library) function f() payable {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Library functions cannot be payable."); } BOOST_AUTO_TEST_CASE(payable_external) @@ -4751,7 +4722,7 @@ BOOST_AUTO_TEST_CASE(payable_internal) function f() payable internal {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal functions cannot be payable."); } BOOST_AUTO_TEST_CASE(payable_private) @@ -4761,7 +4732,7 @@ BOOST_AUTO_TEST_CASE(payable_private) function f() payable private {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal functions cannot be payable."); } BOOST_AUTO_TEST_CASE(illegal_override_payable) @@ -4770,7 +4741,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable) contract B { function f() payable {} } contract C is B { function f() {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Overriding function should be declared payable."); } BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) @@ -4779,7 +4750,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) contract B { function f() {} } contract C is B { function f() payable {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Overriding function should not be declared payable."); } BOOST_AUTO_TEST_CASE(function_variable_mixin) @@ -4797,16 +4768,7 @@ BOOST_AUTO_TEST_CASE(function_variable_mixin) function checkOk() returns (bool) { return ok(); } } )"; - CHECK_ERROR(text, DeclarationError, ""); -} - - -BOOST_AUTO_TEST_CASE(payable_constant_conflict) -{ - char const* text = R"( - contract C { function f() payable constant {} } - )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, DeclarationError, "Identifier already declared."); } BOOST_AUTO_TEST_CASE(calling_payable) @@ -4830,7 +4792,7 @@ BOOST_AUTO_TEST_CASE(calling_nonpayable) function f() { (new receiver()).nopay.value(10)(); } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function () external - did you forget the \"payable\" modifier?"); } BOOST_AUTO_TEST_CASE(non_payable_constructor) @@ -4846,7 +4808,7 @@ BOOST_AUTO_TEST_CASE(non_payable_constructor) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function () returns (contract C) - did you forget the \"payable\" modifier?"); } BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) @@ -4873,7 +4835,7 @@ BOOST_AUTO_TEST_CASE(constant_constructor) function test() constant {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Constructor cannot be defined as constant."); } BOOST_AUTO_TEST_CASE(external_constructor) @@ -4883,7 +4845,7 @@ BOOST_AUTO_TEST_CASE(external_constructor) function test() external {} } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Constructor must be public or internal."); } BOOST_AUTO_TEST_CASE(invalid_array_as_statement) @@ -4894,7 +4856,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement) function test(uint k) { S[k]; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Integer constant expected."); } BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) @@ -4913,7 +4875,7 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"b\" not found or not visible after argument-dependent lookup in bytes memory"); } BOOST_AUTO_TEST_CASE(function_type) @@ -4961,7 +4923,7 @@ BOOST_AUTO_TEST_CASE(private_function_type) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\"."); } BOOST_AUTO_TEST_CASE(public_function_type) @@ -4973,7 +4935,7 @@ BOOST_AUTO_TEST_CASE(public_function_type) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\"."); } BOOST_AUTO_TEST_CASE(payable_internal_function_type) @@ -4983,7 +4945,7 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type) function (uint) internal payable returns (uint) x; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Only external function types can be payable."); } BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) @@ -4996,7 +4958,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the \"payable\" modifier?"); } BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) @@ -5006,7 +4968,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) function() external returns (function () internal) x; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type."); } BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) @@ -5016,7 +4978,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) function(function () internal) external x; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type."); } BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) @@ -5042,7 +5004,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type is not allowed for public or external functions."); } BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) @@ -5054,7 +5016,7 @@ BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type is not allowed for public or external functions."); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal) @@ -5076,7 +5038,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Internal type is not allowed for public or external functions."); } BOOST_AUTO_TEST_CASE(function_type_arrays) @@ -5127,7 +5089,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type_invalid) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) @@ -5139,7 +5101,7 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); } BOOST_AUTO_TEST_CASE(external_function_to_function_type_calldata_parameter) @@ -5222,7 +5184,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) uint public a = 0x42 << -8; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Operator << not compatible with types int_const 66 and int_const -8"); } BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) @@ -5232,7 +5194,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) uint public a = 0x42 >> -8; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and int_const -8"); } BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) @@ -5242,7 +5204,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) uint public a = 0x42 << 0x100000000; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Operator << not compatible with types int_const 66 and int_const 4294967296"); } BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) @@ -5252,7 +5214,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) uint public a = 0x42 >> 0x100000000; } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and int_const 4294967296"); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) @@ -5447,7 +5409,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, TypeError, "Invalid mobile type."); } BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) @@ -5714,7 +5676,7 @@ BOOST_AUTO_TEST_CASE(interface_constructor) function I(); } )"; - CHECK_ERROR(text, TypeError, "Constructor cannot be defined in interfaces"); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Constructor cannot be defined in interfaces"); } BOOST_AUTO_TEST_CASE(interface_functions) @@ -6134,6 +6096,25 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_with_variables) CHECK_WARNING(text, "shadows a builtin symbol"); } +BOOST_AUTO_TEST_CASE(shadowing_builtins_with_storage_variables) +{ + char const* text = R"( + contract C { + uint msg; + } + )"; + CHECK_WARNING(text, "shadows a builtin symbol"); +} + +BOOST_AUTO_TEST_CASE(shadowing_builtin_at_global_scope) +{ + char const* text = R"( + contract msg { + } + )"; + CHECK_WARNING(text, "shadows a builtin symbol"); +} + BOOST_AUTO_TEST_CASE(shadowing_builtins_with_parameters) { char const* text = R"( @@ -6190,6 +6171,28 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_ignores_constructor) CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(function_overload_is_not_shadowing) +{ + char const* text = R"( + contract C { + function f() {} + function f(uint) {} + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(function_override_is_not_shadowing) +{ + char const* text = R"( + contract D { function f() {} } + contract C is D { + function f(uint) {} + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(callable_crash) { char const* text = R"( @@ -6437,7 +6440,7 @@ BOOST_AUTO_TEST_CASE(using_this_in_constructor) CHECK_WARNING(text, "\"this\" used in constructor"); } -BOOST_AUTO_TEST_CASE(do_not_crash_on_not_lalue) +BOOST_AUTO_TEST_CASE(do_not_crash_on_not_lvalue) { // This checks for a bug that caused a crash because of continued analysis. char const* text = R"( @@ -6451,6 +6454,198 @@ BOOST_AUTO_TEST_CASE(do_not_crash_on_not_lalue) CHECK_ERROR_ALLOW_MULTI(text, TypeError, "is not callable"); } +BOOST_AUTO_TEST_CASE(builtin_reject_gas) +{ + char const* text = R"( + contract C { + function f() { + keccak256.gas(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + sha256.gas(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + ripemd160.gas(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + ecrecover.gas(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"gas\" not found or not visible after argument-dependent lookup"); +} + +BOOST_AUTO_TEST_CASE(builtin_reject_value) +{ + char const* text = R"( + contract C { + function f() { + keccak256.value(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + sha256.value(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + ripemd160.value(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); + text = R"( + contract C { + function f() { + ecrecover.value(); + } + } + )"; + CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); +} + +BOOST_AUTO_TEST_CASE(constructor_without_implementation) +{ + char const* text = R"( + contract C { + function C(); + } + )"; + CHECK_ERROR(text, TypeError, "Constructor must be implemented if declared."); +} + +BOOST_AUTO_TEST_CASE(large_storage_array_fine) +{ + char const* text = R"( + contract C { + uint[2**64 - 1] x; + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(large_storage_array_simple) +{ + char const* text = R"( + contract C { + uint[2**64] x; + } + )"; + CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); +} + +BOOST_AUTO_TEST_CASE(large_storage_arrays_combined) +{ + char const* text = R"( + contract C { + uint[200][200][2**30][][2**30] x; + } + )"; + CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); +} + +BOOST_AUTO_TEST_CASE(large_storage_arrays_struct) +{ + char const* text = R"( + contract C { + struct S { uint[2**30] x; uint[2**50] y; } + S[2**20] x; + } + )"; + CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); +} + +BOOST_AUTO_TEST_CASE(large_storage_array_mapping) +{ + char const* text = R"( + contract C { + mapping(uint => uint[2**100]) x; + } + )"; + CHECK_WARNING(text, "covers a large part of storage and thus makes collisions likely"); +} + +BOOST_AUTO_TEST_CASE(library_function_without_implementation) +{ + char const* text = R"( + library L { + function f(); + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + library L { + function f() internal; + } + )"; + CHECK_ERROR(text, TypeError, "Internal library function must be implemented if declared."); + text = R"( + library L { + function f() private; + } + )"; + CHECK_ERROR(text, TypeError, "Internal library function must be implemented if declared."); +} + +BOOST_AUTO_TEST_CASE(experimental_pragma) +{ + char const* text = R"( + pragma experimental; + )"; + CHECK_ERROR(text, SyntaxError, "Experimental feature name is missing."); + text = R"( + pragma experimental 123; + )"; + CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); + text = R"( + pragma experimental unsupportedName; + )"; + CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); + text = R"( + pragma experimental "unsupportedName"; + )"; + CHECK_ERROR(text, SyntaxError, "Unsupported experimental feature name."); + text = R"( + pragma experimental ""; + )"; + CHECK_ERROR(text, SyntaxError, "Empty experimental feature name is invalid."); + text = R"( + pragma experimental unsupportedName unsupportedName; + )"; + CHECK_ERROR(text, SyntaxError, "Stray arguments."); + text = R"( + pragma experimental __test; + )"; + CHECK_WARNING(text, "Experimental features are turned on. Do not use experimental features on live deployments."); +// text = R"( +// pragma experimental __test; +// pragma experimental __test; +// )"; +// CHECK_ERROR_ALLOW_MULTI(text, SyntaxError, "Duplicate experimental feature name."); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 78edd4d1..30dc80d9 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -898,25 +898,31 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) contract c { uint private internal a; })"; - CHECK_PARSE_ERROR(text, "Visibility already specified"); + CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\"."); + text = R"( + contract c { + function f() private external {} + })"; + CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\"."); } -BOOST_AUTO_TEST_CASE(multiple_payable_specifiers) +BOOST_AUTO_TEST_CASE(multiple_statemutability_specifiers) { char const* text = R"( contract c { function f() payable payable {} })"; - CHECK_PARSE_ERROR(text, "Multiple \"payable\" specifiers."); -} - -BOOST_AUTO_TEST_CASE(multiple_constant_specifiers) -{ - char const* text = R"( + CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\"."); + text = R"( contract c { function f() constant constant {} })"; - CHECK_PARSE_ERROR(text, "Multiple \"constant\" specifiers."); + CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\"."); + text = R"( + contract c { + function f() payable constant {} + })"; + CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\"."); } BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) @@ -1182,6 +1188,18 @@ BOOST_AUTO_TEST_CASE(tuples) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(tuples_without_commas) +{ + char const* text = R"( + contract C { + function f() { + var a = (2 2); + } + } + )"; + CHECK_PARSE_ERROR(text, "Expected token Comma"); +} + BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) { char const* text = R"( @@ -1345,6 +1363,42 @@ BOOST_AUTO_TEST_CASE(conditional_with_assignment) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(recursion_depth1) +{ + string text("contract C { bytes"); + for (size_t i = 0; i < 30000; i++) + text += "["; + CHECK_PARSE_ERROR(text.c_str(), "Maximum recursion depth reached during parsing"); +} + +BOOST_AUTO_TEST_CASE(recursion_depth2) +{ + string text("contract C { function f() {"); + for (size_t i = 0; i < 30000; i++) + text += "{"; + CHECK_PARSE_ERROR(text, "Maximum recursion depth reached during parsing"); +} + +BOOST_AUTO_TEST_CASE(recursion_depth3) +{ + string text("contract C { function f() { uint x = f("); + for (size_t i = 0; i < 30000; i++) + text += "("; + CHECK_PARSE_ERROR(text, "Maximum recursion depth reached during parsing"); +} + +BOOST_AUTO_TEST_CASE(recursion_depth4) +{ + string text("contract C { function f() { uint a;"); + for (size_t i = 0; i < 30000; i++) + text += "("; + text += "a"; + for (size_t i = 0; i < 30000; i++) + text += "++)"; + text += "}}"; + CHECK_PARSE_ERROR(text, "Maximum recursion depth reached during parsing"); +} + BOOST_AUTO_TEST_CASE(declaring_fixed_and_ufixed_variables) { char const* text = R"( |
